VSE: Scopes improvements #116798

Merged
Aras Pranckevicius merged 13 commits from aras_p/blender:vse-scopes into main 2024-01-05 22:03:13 +01:00
26 changed files with 812 additions and 875 deletions

View File

@ -34,6 +34,7 @@
#include "DNA_object_types.h"
#include "DNA_screen_types.h"
#include "DNA_sdna_types.h"
#include "DNA_sequence_types.h"
#include "DNA_space_types.h"
#include "DNA_text_types.h"
#include "DNA_view3d_types.h"

View File

@ -50,6 +50,7 @@
#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_sequence_types.h"
#include "DNA_shader_fx_types.h"
#include "DNA_text_types.h"
#include "DNA_texture_types.h"

View File

@ -37,6 +37,7 @@
#include "DNA_pointcloud_types.h"
#include "DNA_rigidbody_types.h"
#include "DNA_screen_types.h"
#include "DNA_sequence_types.h"
#include "DNA_shader_fx_types.h"
#include "DNA_space_types.h"
#include "DNA_text_types.h"

View File

@ -46,6 +46,7 @@
#include "DNA_modifier_types.h"
#include "DNA_movieclip_types.h"
#include "DNA_screen_types.h"
#include "DNA_sequence_types.h"
#include "DNA_space_types.h"
#include "DNA_text_types.h"
#include "DNA_tracking_types.h"

View File

@ -46,6 +46,7 @@ set(SRC
sequencer_intern.hh
sequencer_quads_batch.hh
sequencer_scopes.hh
)
set(LIB
@ -73,6 +74,16 @@ if(WITH_AUDASPACE)
add_definitions(-DWITH_AUDASPACE)
endif()
if(WITH_TBB)
add_definitions(-DWITH_TBB)
list(APPEND INC_SYS
${TBB_INCLUDE_DIRS}
)
list(APPEND LIB
${TBB_LIBRARIES}
)
endif()
blender_add_lib(bf_editor_space_sequencer "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")

View File

@ -179,7 +179,7 @@ static float draw_channel_widget_lock(const SeqChannelDrawContext *context,
static bool channel_is_being_renamed(const SpaceSeq *sseq, const int channel_index)
{
return sseq->runtime.rename_channel_index == channel_index;
return sseq->runtime->rename_channel_index == channel_index;
}
static float text_size_get(const SeqChannelDrawContext *context)
@ -250,7 +250,7 @@ static void draw_channel_labels(const SeqChannelDrawContext *context,
UI_block_emboss_set(block, UI_EMBOSS_NONE);
if (UI_but_active_only(context->C, context->region, block, but) == false) {
sseq->runtime.rename_channel_index = 0;
sseq->runtime->rename_channel_index = 0;
}
WM_event_add_notifier(context->C, NC_SCENE | ND_SEQUENCER, context->scene);

View File

@ -38,7 +38,7 @@ static int sequencer_rename_channel_invoke(bContext *C, wmOperator * /*op*/, con
channel_draw_context_init(C, CTX_wm_region(C), &context);
float mouse_y = UI_view2d_region_to_view_y(context.timeline_region_v2d, event->mval[1]);
sseq->runtime.rename_channel_index = mouse_y;
sseq->runtime->rename_channel_index = mouse_y;
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, CTX_data_scene(C));
return OPERATOR_FINISHED;
}

View File

@ -8,11 +8,14 @@
#pragma once
#include "BLI_utility_mixins.hh"
#include "BLI_vector.hh"
#include "BLI_vector_set.hh"
#include "DNA_sequence_types.h"
#include "RNA_access.hh"
#include "sequencer_scopes.hh"
/* Internal exports only. */
class SeqQuadsBatch;
@ -40,6 +43,24 @@ struct ListBase;
#define DEFAULT_IMG_STRIP_LENGTH 25 /* XXX arbitrary but ok for now. */
#define OVERLAP_ALPHA 180
namespace blender::ed::seq {
struct SpaceSeq_Runtime : public NonCopyable {
/** Required for Thumbnail job start condition. */
rctf last_thumbnail_area = {0, 0, 0, 0};
/** Stores lists of most recently displayed thumbnails. */
GHash *last_displayed_thumbnails = nullptr;
int rename_channel_index = 0;
float timeline_clamp_custom_range = 0;
blender::ed::seq::SeqScopes scopes;
SpaceSeq_Runtime() = default;
~SpaceSeq_Runtime();
};
} // namespace blender::ed::seq
struct SeqChannelDrawContext {
const bContext *C;
ScrArea *area;
@ -258,14 +279,6 @@ void sequencer_dropboxes();
void sequencer_operatortypes();
void sequencer_keymap(wmKeyConfig *keyconf);
/* sequencer_scope.c */
ImBuf *make_waveform_view_from_ibuf(ImBuf *ibuf);
ImBuf *make_sep_waveform_view_from_ibuf(ImBuf *ibuf);
ImBuf *make_vectorscope_view_from_ibuf(ImBuf *ibuf);
ImBuf *make_zebra_view_from_ibuf(ImBuf *ibuf, float perc);
ImBuf *make_histogram_view_from_ibuf(ImBuf *ibuf);
/* `sequencer_buttons.cc` */
void sequencer_buttons_register(ARegionType *art);

View File

@ -9,7 +9,10 @@
#include <cmath>
#include <cstring>
#include "BLF_api.h"
#include "BLI_blenlib.h"
#include "BLI_math_rotation.h"
#include "BLI_utildefines.h"
#include "IMB_imbuf_types.h"
@ -56,8 +59,9 @@
#include "WM_api.hh"
#include "WM_types.hh"
/* Own include. */
#include "sequencer_intern.hh"
#include "sequencer_quads_batch.hh"
#include "sequencer_scopes.hh"
static Sequence *special_seq_update = nullptr;
@ -158,37 +162,9 @@ ImBuf *sequencer_ibuf_get(Main *bmain,
return ibuf;
}
static void sequencer_check_scopes(SequencerScopes *scopes, ImBuf *ibuf)
{
if (scopes->reference_ibuf != ibuf) {
if (scopes->zebra_ibuf) {
IMB_freeImBuf(scopes->zebra_ibuf);
scopes->zebra_ibuf = nullptr;
}
if (scopes->waveform_ibuf) {
IMB_freeImBuf(scopes->waveform_ibuf);
scopes->waveform_ibuf = nullptr;
}
if (scopes->sep_waveform_ibuf) {
IMB_freeImBuf(scopes->sep_waveform_ibuf);
scopes->sep_waveform_ibuf = nullptr;
}
if (scopes->vector_ibuf) {
IMB_freeImBuf(scopes->vector_ibuf);
scopes->vector_ibuf = nullptr;
}
if (scopes->histogram_ibuf) {
IMB_freeImBuf(scopes->histogram_ibuf);
scopes->histogram_ibuf = nullptr;
}
}
}
static ImBuf *sequencer_make_scope(Scene *scene, ImBuf *ibuf, ImBuf *(*make_scope_fn)(ImBuf *ibuf))
static ImBuf *sequencer_make_scope(Scene *scene,
ImBuf *ibuf,
ImBuf *(*make_scope_fn)(const ImBuf *ibuf))
{
ImBuf *display_ibuf = IMB_dupImBuf(ibuf);
ImBuf *scope;
@ -451,11 +427,9 @@ static void sequencer_draw_display_buffer(const bContext *C,
ARegion *region,
SpaceSeq *sseq,
ImBuf *ibuf,
ImBuf *scope,
bool draw_overlay,
bool draw_backdrop)
{
void *display_buffer;
void *buffer_cache_handle = nullptr;
if (sseq->mainb == SEQ_DRAW_IMG_IMBUF && sseq->flag & SEQ_USE_ALPHA) {
@ -472,21 +446,8 @@ static void sequencer_draw_display_buffer(const bContext *C,
uint texCoord = GPU_vertformat_attr_add(
imm_format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
if (scope) {
ibuf = scope;
if (ibuf->float_buffer.data && ibuf->byte_buffer.data == nullptr) {
IMB_rect_from_float(ibuf);
}
display_buffer = ibuf->byte_buffer.data;
format = GPU_RGBA8;
data = GPU_DATA_UBYTE;
}
else {
display_buffer = sequencer_OCIO_transform_ibuf(
C, ibuf, &glsl_used, &format, &data, &buffer_cache_handle);
}
void *display_buffer = sequencer_OCIO_transform_ibuf(
C, ibuf, &glsl_used, &format, &data, &buffer_cache_handle);
if (draw_backdrop) {
GPU_matrix_push();
@ -558,68 +519,350 @@ static void sequencer_draw_display_buffer(const bContext *C,
}
}
static ImBuf *sequencer_get_scope(Scene *scene, SpaceSeq *sseq, ImBuf *ibuf, bool draw_backdrop)
static void draw_histogram(ARegion *region,
const blender::ed::seq::ScopeHistogram &hist,
SeqQuadsBatch &quads,
const rctf &area)
{
ImBuf *scope = nullptr;
SequencerScopes *scopes = &sseq->scopes;
using namespace blender::ed::seq;
if (hist.data.is_empty()) {
return;
}
if (!draw_backdrop && (sseq->mainb != SEQ_DRAW_IMG_IMBUF || sseq->zebra != 0)) {
sequencer_check_scopes(scopes, ibuf);
/* Background. */
uchar col_bg[4] = {0, 0, 0, 255};
quads.add_quad(area.xmin, area.ymin, area.xmax, area.ymax, col_bg);
switch (sseq->mainb) {
case SEQ_DRAW_IMG_IMBUF:
if (!scopes->zebra_ibuf) {
/* Grid lines and labels. */
uchar col_grid[4] = {128, 128, 128, 128};
float grid_x_0 = area.xmin;
float grid_x_1 = area.xmax;
/* Float histograms show more than 0..1 range horizontally. */
if (hist.is_float_hist()) {
float ratio_0 = ratiof(ScopeHistogram::FLOAT_VAL_MIN, ScopeHistogram::FLOAT_VAL_MAX, 0.0f);
float ratio_1 = ratiof(ScopeHistogram::FLOAT_VAL_MIN, ScopeHistogram::FLOAT_VAL_MAX, 1.0f);
grid_x_0 = area.xmin + (area.xmax - area.xmin) * ratio_0;
grid_x_1 = area.xmin + (area.xmax - area.xmin) * ratio_1;
}
if (ibuf->float_buffer.data) {
ImBuf *display_ibuf = IMB_dupImBuf(ibuf);
IMB_colormanagement_imbuf_make_display_space(
display_ibuf, &scene->view_settings, &scene->display_settings);
scopes->zebra_ibuf = make_zebra_view_from_ibuf(display_ibuf, sseq->zebra);
IMB_freeImBuf(display_ibuf);
}
else {
scopes->zebra_ibuf = make_zebra_view_from_ibuf(ibuf, sseq->zebra);
}
}
scope = scopes->zebra_ibuf;
break;
case SEQ_DRAW_IMG_WAVEFORM:
if ((sseq->flag & SEQ_DRAW_COLOR_SEPARATED) != 0) {
if (!scopes->sep_waveform_ibuf) {
scopes->sep_waveform_ibuf = sequencer_make_scope(
scene, ibuf, make_sep_waveform_view_from_ibuf);
}
scope = scopes->sep_waveform_ibuf;
}
else {
if (!scopes->waveform_ibuf) {
scopes->waveform_ibuf = sequencer_make_scope(
scene, ibuf, make_waveform_view_from_ibuf);
}
scope = scopes->waveform_ibuf;
}
break;
case SEQ_DRAW_IMG_VECTORSCOPE:
if (!scopes->vector_ibuf) {
scopes->vector_ibuf = sequencer_make_scope(scene, ibuf, make_vectorscope_view_from_ibuf);
}
scope = scopes->vector_ibuf;
break;
case SEQ_DRAW_IMG_HISTOGRAM:
if (!scopes->histogram_ibuf) {
scopes->histogram_ibuf = sequencer_make_scope(
scene, ibuf, make_histogram_view_from_ibuf);
}
scope = scopes->histogram_ibuf;
break;
View2D *v2d = &region->v2d;
float text_scale_x, text_scale_y;
UI_view2d_scale_get_inverse(v2d, &text_scale_x, &text_scale_y);
for (int line = 0; line <= 4; line++) {
float val = float(line) / 4;
float x = grid_x_0 + (grid_x_1 - grid_x_0) * val;
quads.add_line(x, area.ymin, x, area.ymax, col_grid);
aras_p marked this conversation as resolved
Review

Use BLI_snprintf()

Use `BLI_snprintf()`
/* Label. */
char buf[10];
BLI_snprintf(buf, sizeof(buf), "%.2f", val);
size_t buf_len = strlen(buf);
float text_width, text_height;
BLF_width_and_height(BLF_default(), buf, buf_len, &text_width, &text_height);
text_width *= text_scale_x;
text_height *= text_scale_y;
UI_view2d_text_cache_add(
v2d, x - text_width / 2, area.ymax - text_height * 1.3f, buf, buf_len, col_grid);
}
/* Border. */
uchar col_border[4] = {64, 64, 64, 128};
quads.add_wire_quad(area.xmin, area.ymin, area.xmax, area.ymax, col_border);
/* Histogram area & line for each R/G/B channels, additively blended. */
quads.draw();
GPU_blend(GPU_BLEND_ADDITIVE);
for (int ch = 0; ch < 3; ++ch) {
if (hist.max_value[ch] == 0) {
continue;
}
uchar col_line[4] = {32, 32, 32, 255};
uchar col_area[4] = {64, 64, 64, 128};
col_line[ch] = 224;
col_area[ch] = 224;
float y_scale = (area.ymax - area.ymin) / hist.max_value[ch] * 0.95f;
float x_scale = (area.xmax - area.xmin) / hist.data.size();
float yb = area.ymin;
for (int bin = 0; bin < hist.data.size() - 1; bin++) {
float x0 = area.xmin + (bin + 0.5f) * x_scale;
float x1 = area.xmin + (bin + 1.5f) * x_scale;
/* Future files may have new scopes we don't catch above. */
if (scope) {
scopes->reference_ibuf = ibuf;
float y0 = area.ymin + hist.data[bin][ch] * y_scale;
float y1 = area.ymin + hist.data[bin + 1][ch] * y_scale;
quads.add_quad(x0, yb, x0, y0, x1, yb, x1, y1, col_area);
quads.add_line(x0, y0, x1, y1, col_line);
}
}
return scope;
quads.draw();
GPU_blend(GPU_BLEND_ALPHA);
UI_view2d_text_cache_draw(region);
}
static blender::float2 rgb_to_uv(const blender::float3 &rgb)
{
float y, u, v;
rgb_to_yuv(rgb.x, rgb.y, rgb.z, &y, &u, &v, BLI_YUV_ITU_BT709);
return blender::float2(u, v);
}
static void draw_waveform_graticule(ARegion *region, SeqQuadsBatch &quads, const rctf &area)
{
/* Horizontal lines at 10%, 70%, 90%. */
const float lines[3] = {0.1f, 0.7f, 0.9f};
uchar col_grid[4] = {160, 64, 64, 128};
const float x0 = area.xmin;
const float x1 = area.xmax;
for (int i = 0; i < 3; i++) {
aras_p marked this conversation as resolved
Review

Use BLI_snprintf()

Use `BLI_snprintf()`
const float y = area.ymin + (area.ymax - area.ymin) * lines[i];
char buf[10];
BLI_snprintf(buf, sizeof(buf), "%.1f", lines[i]);
quads.add_line(x0, y, x1, y, col_grid);
UI_view2d_text_cache_add(&region->v2d, x0 + 8, y + 8, buf, strlen(buf), col_grid);
}
/* Border. */
uchar col_border[4] = {64, 64, 64, 128};
quads.add_wire_quad(x0, area.ymin, x1, area.ymax, col_border);
quads.draw();
UI_view2d_text_cache_draw(region);
}
static void draw_vectorscope_graticule(SeqQuadsBatch &quads, const rctf &area)
{
using namespace blender;
GPU_blend(GPU_BLEND_ALPHA);
const float skin_rad = DEG2RADF(123.0f); /* angle in radians of the skin tone line */
const float w = BLI_rctf_size_x(&area);
const float h = BLI_rctf_size_y(&area);
const float centerx = BLI_rctf_cent_x(&area);
const float centery = BLI_rctf_cent_y(&area);
const float rad_base = ((w < h) ? w : h) * 0.5f;
/* vectorscope image is scaled over YUV range, +/- (0.436, 0.615) */
const float rad_x = rad_base * (0.5f / 0.436f);
const float rad_y = rad_base * (0.5f / 0.615f);
/* center cross */
uchar col_grid[4] = {128, 128, 128, 96};
quads.add_line(centerx - rad_base * 0.1f, centery, centerx + rad_base * 0.1f, centery, col_grid);
quads.add_line(centerx, centery - rad_base * 0.1f, centerx, centery + rad_base * 0.1f, col_grid);
/* fully saturated vs "safe" (0.75) colored areas */
const float3 primaries[6] = {
{1, 0, 0},
{1, 1, 0},
{0, 1, 0},
{0, 1, 1},
{0, 0, 1},
{1, 0, 1},
};
float2 center{centerx, centery};
float2 rad_scale{rad_x * 2, rad_y * 2};
for (int i = 0; i < 6; i++) {
float3 prim0 = primaries[i];
float3 prim1 = primaries[(i + 1) % 6];
float3 safe0 = prim0 * 0.75f;
float3 safe1 = prim1 * 0.75f;
float2 uv0 = center + rgb_to_uv(prim0) * rad_scale;
float2 uv1 = center + rgb_to_uv(prim1) * rad_scale;
float2 uv2 = center + rgb_to_uv(safe0) * rad_scale;
float2 uv3 = center + rgb_to_uv(safe1) * rad_scale;
uchar col0[4] = {uchar(prim0.x * 255), uchar(prim0.y * 255), uchar(prim0.z * 255), 64};
uchar col1[4] = {uchar(prim1.x * 255), uchar(prim1.y * 255), uchar(prim1.z * 255), 64};
uchar col2[4] = {uchar(safe0.x * 255), uchar(safe0.y * 255), uchar(safe0.z * 255), 64};
uchar col3[4] = {uchar(safe1.x * 255), uchar(safe1.y * 255), uchar(safe1.z * 255), 64};
quads.add_quad(uv0.x, uv0.y, uv1.x, uv1.y, uv2.x, uv2.y, uv3.x, uv3.y, col0, col1, col2, col3);
col0[3] = col1[3] = col2[3] = col3[3] = 192;
quads.add_line(uv0.x, uv0.y, uv1.x, uv1.y, col0, col1);
quads.add_line(uv2.x, uv2.y, uv3.x, uv3.y, col2, col3);
}
/* skin tone line */
uchar col_tone[4] = {255, 102, 0, 128};
const float tone_line_len = 0.895f; /* makes it end at outer edge of saturation ring. */
quads.add_line(centerx,
centery,
centerx + cosf(skin_rad) * rad_x * tone_line_len,
centery + sinf(skin_rad) * rad_y * tone_line_len,
col_tone);
}
static void sequencer_draw_scopes(Scene *scene, ARegion *region, SpaceSeq *sseq)
{
using namespace blender::ed::seq;
/* Figure out draw coordinates. */
rctf preview;
sequencer_preview_get_rect(&preview, scene, region, sseq, false, false);
rctf uv;
BLI_rctf_init(&uv, 0.0f, 1.0f, 0.0f, 1.0f);
const bool keep_aspect = sseq->mainb == SEQ_DRAW_IMG_VECTORSCOPE;
float vecscope_aspect = 1.0f;
if (keep_aspect) {
float width = std::max(BLI_rctf_size_x(&preview), 0.1f);
float height = std::max(BLI_rctf_size_y(&preview), 0.1f);
vecscope_aspect = width / height;
if (vecscope_aspect >= 1.0f) {
BLI_rctf_resize_x(&uv, vecscope_aspect);
}
else {
BLI_rctf_resize_y(&uv, 1.0f / vecscope_aspect);
}
}
SeqQuadsBatch quads;
SeqScopes *scopes = &sseq->runtime->scopes;
/* Draw scope image if there is one. */
bool use_blend = sseq->mainb == SEQ_DRAW_IMG_IMBUF && sseq->flag & SEQ_USE_ALPHA;
ImBuf *scope_image = nullptr;
if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
scope_image = scopes->zebra_ibuf;
}
else if (sseq->mainb == SEQ_DRAW_IMG_WAVEFORM) {
scope_image = (sseq->flag & SEQ_DRAW_COLOR_SEPARATED) != 0 ? scopes->sep_waveform_ibuf :
scopes->waveform_ibuf;
}
else if (sseq->mainb == SEQ_DRAW_IMG_VECTORSCOPE) {
scope_image = scopes->vector_ibuf;
}
else if (sseq->mainb == SEQ_DRAW_IMG_HISTOGRAM) {
use_blend = true;
}
if (use_blend) {
GPU_blend(GPU_BLEND_ALPHA);
}
if (scope_image != nullptr) {
if (scope_image->float_buffer.data && scope_image->byte_buffer.data == nullptr) {
IMB_rect_from_float(scope_image);
}
eGPUTextureFormat format = GPU_RGBA8;
eGPUDataFormat data = GPU_DATA_UBYTE;
eGPUTextureUsage usage = GPU_TEXTURE_USAGE_SHADER_READ | GPU_TEXTURE_USAGE_ATTACHMENT;
GPUTexture *texture = GPU_texture_create_2d(
"seq_display_buf", scope_image->x, scope_image->y, 1, format, usage, nullptr);
GPU_texture_update(texture, data, scope_image->byte_buffer.data);
GPU_texture_filter_mode(texture, false);
GPU_texture_extend_mode(texture, GPU_SAMPLER_EXTEND_MODE_CLAMP_TO_BORDER);
GPU_texture_bind(texture, 0);
GPUVertFormat *imm_format = immVertexFormat();
uint pos = GPU_vertformat_attr_add(imm_format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
uint texCoord = GPU_vertformat_attr_add(
imm_format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_IMAGE_COLOR);
immUniformColor3f(1.0f, 1.0f, 1.0f);
immBegin(GPU_PRIM_TRI_FAN, 4);
immAttr2f(texCoord, uv.xmin, uv.ymin);
immVertex2f(pos, preview.xmin, preview.ymin);
immAttr2f(texCoord, uv.xmin, uv.ymax);
immVertex2f(pos, preview.xmin, preview.ymax);
immAttr2f(texCoord, uv.xmax, uv.ymax);
immVertex2f(pos, preview.xmax, preview.ymax);
immAttr2f(texCoord, uv.xmax, uv.ymin);
immVertex2f(pos, preview.xmax, preview.ymin);
immEnd();
GPU_texture_unbind(texture);
GPU_texture_free(texture);
immUnbindProgram();
}
if (sseq->mainb == SEQ_DRAW_IMG_HISTOGRAM) {
draw_histogram(region, scopes->histogram, quads, preview);
}
if (sseq->mainb == SEQ_DRAW_IMG_WAVEFORM) {
use_blend = true;
draw_waveform_graticule(region, quads, preview);
}
if (sseq->mainb == SEQ_DRAW_IMG_VECTORSCOPE) {
use_blend = true;
draw_vectorscope_graticule(quads, preview);
}
quads.draw();
if (use_blend) {
GPU_blend(GPU_BLEND_NONE);
}
}
static bool sequencer_calc_scopes(Scene *scene, SpaceSeq *sseq, ImBuf *ibuf, bool draw_backdrop)
{
using namespace blender::ed::seq;
if (draw_backdrop || (sseq->mainb == SEQ_DRAW_IMG_IMBUF && sseq->zebra == 0)) {
return false; /* Not drawing any scopes. */
}
SeqScopes *scopes = &sseq->runtime->scopes;
if (scopes->reference_ibuf != ibuf) {
scopes->cleanup();
}
switch (sseq->mainb) {
case SEQ_DRAW_IMG_IMBUF:
if (!scopes->zebra_ibuf) {
if (ibuf->float_buffer.data) {
ImBuf *display_ibuf = IMB_dupImBuf(ibuf);
IMB_colormanagement_imbuf_make_display_space(
display_ibuf, &scene->view_settings, &scene->display_settings);
scopes->zebra_ibuf = make_zebra_view_from_ibuf(display_ibuf, sseq->zebra);
IMB_freeImBuf(display_ibuf);
}
else {
scopes->zebra_ibuf = make_zebra_view_from_ibuf(ibuf, sseq->zebra);
}
}
break;
case SEQ_DRAW_IMG_WAVEFORM:
if ((sseq->flag & SEQ_DRAW_COLOR_SEPARATED) != 0) {
if (!scopes->sep_waveform_ibuf) {
scopes->sep_waveform_ibuf = sequencer_make_scope(
scene, ibuf, make_sep_waveform_view_from_ibuf);
}
}
else {
if (!scopes->waveform_ibuf) {
scopes->waveform_ibuf = sequencer_make_scope(scene, ibuf, make_waveform_view_from_ibuf);
}
}
break;
case SEQ_DRAW_IMG_VECTORSCOPE:
if (!scopes->vector_ibuf) {
scopes->vector_ibuf = sequencer_make_scope(scene, ibuf, make_vectorscope_view_from_ibuf);
}
break;
case SEQ_DRAW_IMG_HISTOGRAM: {
ImBuf *display_ibuf = IMB_dupImBuf(ibuf);
IMB_colormanagement_imbuf_make_display_space(
display_ibuf, &scene->view_settings, &scene->display_settings);
scopes->histogram.calc_from_ibuf(display_ibuf);
IMB_freeImBuf(display_ibuf);
} break;
default: /* Future files might have scopes we don't know about. */
return false;
}
scopes->reference_ibuf = ibuf;
return true;
}
bool sequencer_draw_get_transform_preview(SpaceSeq *sseq, Scene *scene)
@ -732,7 +975,6 @@ void sequencer_draw_preview(const bContext *C,
Depsgraph *depsgraph = CTX_data_expect_evaluated_depsgraph(C);
View2D *v2d = &region->v2d;
ImBuf *ibuf = nullptr;
ImBuf *scope = nullptr;
float viewrect[2];
const bool show_imbuf = ED_space_sequencer_check_show_imbuf(sseq);
const bool draw_gpencil = ((sseq->preview_overlay.flag & SEQ_PREVIEW_SHOW_GPENCIL) && sseq->gpd);
@ -781,13 +1023,17 @@ void sequencer_draw_preview(const bContext *C,
}
if (ibuf) {
scope = sequencer_get_scope(scene, sseq, ibuf, draw_backdrop);
bool has_scope = sequencer_calc_scopes(scene, sseq, ibuf, draw_backdrop);
if (has_scope) {
/* Draw scope. */
sequencer_draw_scopes(scene, region, sseq);
}
else {
/* Draw image. */
sequencer_draw_display_buffer(C, scene, region, sseq, ibuf, draw_overlay, draw_backdrop);
}
/* Draw image. */
sequencer_draw_display_buffer(
C, scene, region, sseq, ibuf, scope, draw_overlay, draw_backdrop);
/* Draw over image. */
/* Draw metadata. */
if (sseq->preview_overlay.flag & SEQ_PREVIEW_SHOW_METADATA && sseq->flag & SEQ_SHOW_OVERLAY) {
ED_region_image_metadata_draw(0.0, 0.0, ibuf, &v2d->tot, 1.0, 1.0);
}
@ -821,7 +1067,6 @@ void sequencer_draw_preview(const bContext *C,
ED_region_draw_cb_draw(C, region, REGION_DRAW_POST_VIEW);
GPU_framebuffer_bind_no_srgb(framebuffer_overlay);
/* Scope is freed in sequencer_check_scopes when `ibuf` changes and redraw is needed. */
if (ibuf) {
IMB_freeImBuf(ibuf);
}

View File

@ -53,10 +53,10 @@ SeqQuadsBatch::SeqQuadsBatch()
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);
GPU_batch_program_set_builtin(batch_quads, GPU_SHADER_3D_SMOOTH_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);
GPU_batch_program_set_builtin(batch_lines, GPU_SHADER_3D_SMOOTH_COLOR);
}
SeqQuadsBatch::~SeqQuadsBatch()
@ -93,7 +93,10 @@ void SeqQuadsBatch::add_quad(float x1,
float y3,
float x4,
float y4,
const uchar color[4])
const uchar color1[4],
const uchar color2[4],
const uchar color3[4],
const uchar color4[4])
{
if (quads_num >= MAX_QUADS) {
draw();
@ -103,10 +106,10 @@ void SeqQuadsBatch::add_quad(float x1,
BLI_assert(verts_quads != nullptr);
}
ColorVertex v0 = {blender::float2(x1, y1), color};
ColorVertex v1 = {blender::float2(x2, y2), color};
ColorVertex v2 = {blender::float2(x3, y3), color};
ColorVertex v3 = {blender::float2(x4, y4), color};
ColorVertex v0 = {blender::float2(x1, y1), color1};
ColorVertex v1 = {blender::float2(x2, y2), color2};
ColorVertex v2 = {blender::float2(x3, y3), color3};
ColorVertex v3 = {blender::float2(x4, y4), color4};
*verts_quads++ = v0;
*verts_quads++ = v1;
@ -147,7 +150,8 @@ void SeqQuadsBatch::add_wire_quad(float x1, float y1, float x2, float y2, const
lines_num += 4;
}
void SeqQuadsBatch::add_line(float x1, float y1, float x2, float y2, const uchar color[4])
void SeqQuadsBatch::add_line(
float x1, float y1, float x2, float y2, const uchar color1[4], const uchar color2[4])
{
if (lines_num + 1 > MAX_LINES) {
draw();
@ -157,8 +161,8 @@ void SeqQuadsBatch::add_line(float x1, float y1, float x2, float y2, const uchar
BLI_assert(verts_lines != nullptr);
}
ColorVertex v0 = {blender::float2(x1, y1), color};
ColorVertex v1 = {blender::float2(x2, y2), color};
ColorVertex v0 = {blender::float2(x1, y1), color1};
ColorVertex v1 = {blender::float2(x2, y2), color2};
*verts_lines++ = v0;
*verts_lines++ = v1;

View File

@ -33,9 +33,9 @@ class SeqQuadsBatch {
/** 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_quad(x1, y1, x1, y2, x2, y1, x2, y2, color, color, color, color);
}
/** Add a quad. */
/** Add a quad with four arbitrary coordinates and one color. */
void add_quad(float x1,
float y1,
float x2,
@ -44,11 +44,33 @@ class SeqQuadsBatch {
float y3,
float x4,
float y4,
const uchar color[4]);
const uchar color[4])
{
add_quad(x1, y1, x2, y2, x3, y3, x4, y4, color, color, color, color);
}
/** Add a quad with four arbitrary coordinates and a color for each. */
void add_quad(float x1,
float y1,
float x2,
float y2,
float x3,
float y3,
float x4,
float y4,
const uchar color1[4],
const uchar color2[4],
const uchar color3[4],
const uchar color4[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]);
/** Add a line with single color. */
void add_line(float x1, float y1, float x2, float y2, const uchar color[4])
{
add_line(x1, y1, x2, y2, color, color);
}
/** Add a line with two endpoint colors. */
void add_line(
float x1, float y1, float x2, float y2, const uchar color1[4], const uchar color2[4]);
private:
static constexpr int MAX_QUADS = 1024;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,55 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup spseq
*/
#pragma once
#include "BLI_array.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_utility_mixins.hh"
struct ImBuf;
namespace blender::ed::seq {
struct ScopeHistogram {
/* Byte images just have bins for the 0..255 range. */
static constexpr int BINS_BYTE = 256;
/* Float images spead -0.25..+1.25 range over 512 bins. */
static constexpr int BINS_FLOAT = 512;
static constexpr float FLOAT_VAL_MIN = -0.25f;
static constexpr float FLOAT_VAL_MAX = 1.25f;
Array<uint3> data;
uint3 max_value;
void calc_from_ibuf(const ImBuf *ibuf);
bool is_float_hist() const
{
return data.size() == BINS_FLOAT;
}
};
struct SeqScopes : public NonCopyable {
ImBuf *reference_ibuf = nullptr;
ImBuf *zebra_ibuf = nullptr;
ImBuf *waveform_ibuf = nullptr;
ImBuf *sep_waveform_ibuf = nullptr;
ImBuf *vector_ibuf = nullptr;
ScopeHistogram histogram;
SeqScopes() = default;
~SeqScopes();
void cleanup();
};
ImBuf *make_waveform_view_from_ibuf(const ImBuf *ibuf);
ImBuf *make_sep_waveform_view_from_ibuf(const ImBuf *ibuf);
ImBuf *make_vectorscope_view_from_ibuf(const ImBuf *ibuf);
ImBuf *make_zebra_view_from_ibuf(const ImBuf *ibuf, float perc);
} // namespace blender::ed::seq

View File

@ -295,21 +295,21 @@ static void sequencer_thumbnail_start_job_if_necessary(
/* Job start requested, but over area which has been processed. Unless `thumbnail_is_missing` is
* true, ignore this request as all images are in view. */
if (v2d->cur.xmax == sseq->runtime.last_thumbnail_area.xmax &&
v2d->cur.ymax == sseq->runtime.last_thumbnail_area.ymax && !thumbnail_is_missing)
if (v2d->cur.xmax == sseq->runtime->last_thumbnail_area.xmax &&
v2d->cur.ymax == sseq->runtime->last_thumbnail_area.ymax && !thumbnail_is_missing)
{
return;
}
/* Stop the job first as view has changed. Pointless to continue old job. */
if (v2d->cur.xmax != sseq->runtime.last_thumbnail_area.xmax ||
v2d->cur.ymax != sseq->runtime.last_thumbnail_area.ymax)
if (v2d->cur.xmax != sseq->runtime->last_thumbnail_area.xmax ||
v2d->cur.ymax != sseq->runtime->last_thumbnail_area.ymax)
{
WM_jobs_stop(CTX_wm_manager(C), nullptr, thumbnail_start_job);
}
sequencer_thumbnail_init_job(C, v2d, ed, thumb_height);
sseq->runtime.last_thumbnail_area = v2d->cur;
sseq->runtime->last_thumbnail_area = v2d->cur;
}
void last_displayed_thumbnails_list_free(void *val)
@ -320,15 +320,15 @@ void last_displayed_thumbnails_list_free(void *val)
static GSet *last_displayed_thumbnails_list_ensure(const bContext *C, Sequence *seq)
{
SpaceSeq *sseq = CTX_wm_space_seq(C);
if (sseq->runtime.last_displayed_thumbnails == nullptr) {
sseq->runtime.last_displayed_thumbnails = BLI_ghash_ptr_new(__func__);
if (sseq->runtime->last_displayed_thumbnails == nullptr) {
sseq->runtime->last_displayed_thumbnails = BLI_ghash_ptr_new(__func__);
}
GSet *displayed_thumbnails = static_cast<GSet *>(
BLI_ghash_lookup(sseq->runtime.last_displayed_thumbnails, seq));
BLI_ghash_lookup(sseq->runtime->last_displayed_thumbnails, seq));
if (displayed_thumbnails == nullptr) {
displayed_thumbnails = BLI_gset_int_new(__func__);
BLI_ghash_insert(sseq->runtime.last_displayed_thumbnails, seq, displayed_thumbnails);
BLI_ghash_insert(sseq->runtime->last_displayed_thumbnails, seq, displayed_thumbnails);
}
return displayed_thumbnails;

View File

@ -62,8 +62,15 @@
static void sequencer_scopes_tag_refresh(ScrArea *area)
{
SpaceSeq *sseq = (SpaceSeq *)area->spacedata.first;
sseq->runtime->scopes.reference_ibuf = nullptr;
}
sseq->scopes.reference_ibuf = nullptr;
blender::ed::seq::SpaceSeq_Runtime::~SpaceSeq_Runtime()
{
if (last_displayed_thumbnails != nullptr) {
BLI_ghash_free(last_displayed_thumbnails, nullptr, last_displayed_thumbnails_list_free);
last_displayed_thumbnails = nullptr;
}
}
/* ******************** manage regions ********************* */
@ -98,9 +105,6 @@ static SpaceLink *sequencer_create(const ScrArea * /*area*/, const Scene *scene)
SEQ_TIMELINE_SHOW_FCURVES | SEQ_TIMELINE_SHOW_STRIP_COLOR_TAG |
SEQ_TIMELINE_SHOW_STRIP_RETIMING | SEQ_TIMELINE_ALL_WAVEFORMS;
BLI_rctf_init(&sseq->runtime.last_thumbnail_area, 0.0f, 0.0f, 0.0f, 0.0f);
sseq->runtime.last_displayed_thumbnails = nullptr;
/* Header. */
region = MEM_cnew<ARegion>("header for sequencer");
@ -192,8 +196,6 @@ static SpaceLink *sequencer_create(const ScrArea * /*area*/, const Scene *scene)
region->v2d.flag |= V2D_VIEWSYNC_AREA_VERTICAL;
region->v2d.align = V2D_ALIGN_NO_NEG_Y;
sseq->runtime.last_displayed_thumbnails = nullptr;
return (SpaceLink *)sseq;
}
@ -201,43 +203,23 @@ static SpaceLink *sequencer_create(const ScrArea * /*area*/, const Scene *scene)
static void sequencer_free(SpaceLink *sl)
{
SpaceSeq *sseq = (SpaceSeq *)sl;
SequencerScopes *scopes = &sseq->scopes;
MEM_delete(sseq->runtime);
#if 0
if (sseq->gpd) {
BKE_gpencil_free_data(sseq->gpd);
}
#endif
if (scopes->zebra_ibuf) {
IMB_freeImBuf(scopes->zebra_ibuf);
}
if (scopes->waveform_ibuf) {
IMB_freeImBuf(scopes->waveform_ibuf);
}
if (scopes->sep_waveform_ibuf) {
IMB_freeImBuf(scopes->sep_waveform_ibuf);
}
if (scopes->vector_ibuf) {
IMB_freeImBuf(scopes->vector_ibuf);
}
if (scopes->histogram_ibuf) {
IMB_freeImBuf(scopes->histogram_ibuf);
}
if (sseq->runtime.last_displayed_thumbnails) {
BLI_ghash_free(
sseq->runtime.last_displayed_thumbnails, nullptr, last_displayed_thumbnails_list_free);
sseq->runtime.last_displayed_thumbnails = nullptr;
}
}
/* Space-type init callback. */
static void sequencer_init(wmWindowManager * /*wm*/, ScrArea * /*area*/) {}
static void sequencer_init(wmWindowManager * /*wm*/, ScrArea *area)
{
SpaceSeq *sseq = (SpaceSeq *)area->spacedata.first;
if (sseq->runtime == nullptr) {
sseq->runtime = MEM_new<SpaceSeq_Runtime>(__func__);
}
}
static void sequencer_refresh(const bContext *C, ScrArea *area)
{
@ -301,13 +283,11 @@ static void sequencer_refresh(const bContext *C, ScrArea *area)
static SpaceLink *sequencer_duplicate(SpaceLink *sl)
{
SpaceSeq *sseqn = static_cast<SpaceSeq *>(MEM_dupallocN(sl));
sseqn->runtime = MEM_new<SpaceSeq_Runtime>(__func__);
/* Clear or remove stuff from old. */
// sseq->gpd = gpencil_data_duplicate(sseq->gpd, false);
memset(&sseqn->scopes, 0, sizeof(sseqn->scopes));
memset(&sseqn->runtime, 0, sizeof(sseqn->runtime));
return (SpaceLink *)sseqn;
}
@ -534,7 +514,7 @@ static void sequencer_main_clamp_view(const bContext *C, ARegion *region)
}
/* If strip is deleted, don't move view automatically, keep current range until it is changed. */
strip_boundbox.ymax = max_ff(sseq->runtime.timeline_clamp_custom_range, strip_boundbox.ymax);
strip_boundbox.ymax = max_ff(sseq->runtime->timeline_clamp_custom_range, strip_boundbox.ymax);
rctf view_clamped = v2d->cur;
@ -557,7 +537,7 @@ static void sequencer_main_region_clamp_custom_set(const bContext *C, ARegion *r
View2D *v2d = &region->v2d;
if ((v2d->flag & V2D_IS_NAVIGATING) == 0) {
sseq->runtime.timeline_clamp_custom_range = v2d->cur.ymax;
sseq->runtime->timeline_clamp_custom_range = v2d->cur.ymax;
}
}
@ -960,6 +940,8 @@ static void sequencer_space_blend_read_data(BlendDataReader * /*reader*/, SpaceL
{
SpaceSeq *sseq = (SpaceSeq *)sl;
sseq->runtime = nullptr;
/* grease pencil data is not a direct data and can't be linked from direct_link*
* functions, it should be linked from lib_link* functions instead
*
@ -973,13 +955,6 @@ static void sequencer_space_blend_read_data(BlendDataReader * /*reader*/, SpaceL
BKE_gpencil_blend_read_data(fd, sseq->gpd);
}
#endif
sseq->scopes.reference_ibuf = nullptr;
sseq->scopes.zebra_ibuf = nullptr;
sseq->scopes.waveform_ibuf = nullptr;
sseq->scopes.sep_waveform_ibuf = nullptr;
sseq->scopes.vector_ibuf = nullptr;
sseq->scopes.histogram_ibuf = nullptr;
memset(&sseq->runtime, 0x0, sizeof(sseq->runtime));
}
static void sequencer_space_blend_write(BlendWriter *writer, SpaceLink *sl)

View File

@ -6,6 +6,7 @@
* \ingroup edtransform
*/
#include "DNA_sequence_types.h"
#include "DNA_space_types.h"
#include "MEM_guardedalloc.h"

View File

@ -8,6 +8,7 @@
#include "MEM_guardedalloc.h"
#include "DNA_sequence_types.h"
#include "DNA_space_types.h"
#include "BLI_listbase.h"

View File

@ -8,6 +8,7 @@
#include "MEM_guardedalloc.h"
#include "DNA_sequence_types.h"
#include "DNA_space_types.h"
#include "BLI_listbase.h"

View File

@ -19,6 +19,7 @@
#include "DNA_object_types.h"
#include "DNA_screen_types.h"
#include "DNA_sequence_types.h"
#include "DNA_space_types.h"
#include "DNA_view3d_types.h"

View File

@ -14,6 +14,8 @@
#include "BKE_context.hh"
#include "DNA_sequence_types.h"
#include "ED_screen.hh"
#include "ED_transform.hh"

View File

@ -16,6 +16,7 @@
#include "DNA_image_types.h"
#include "DNA_movieclip_types.h"
#include "DNA_scene_types.h"
#include "DNA_sequence_types.h"
#include "DNA_space_types.h"
#include "IMB_filetype.h"

View File

@ -545,19 +545,9 @@ typedef struct SoundEqualizerModifierData {
/** \} */
/* -------------------------------------------------------------------- */
/** \name Scopes
/** \name Flags & Types
* \{ */
typedef struct SequencerScopes {
struct ImBuf *reference_ibuf;
struct ImBuf *zebra_ibuf;
struct ImBuf *waveform_ibuf;
struct ImBuf *sep_waveform_ibuf;
struct ImBuf *vector_ibuf;
struct ImBuf *histogram_ibuf;
} SequencerScopes;
#define MAXSEQ 128
/** #Editor::overlay_frame_flag */
@ -583,12 +573,6 @@ enum {
SEQ_SPEED_USE_INTERPOLATION = 1 << 3,
};
/** \} */
/* -------------------------------------------------------------------- */
/** \name Flags & Types
* \{ */
#define SEQ_NAME_MAXSTR 64
/* From: `DNA_object_types.h`, see it's doc-string there. */

View File

@ -19,7 +19,6 @@
#include "DNA_movieclip_types.h" /* MovieClipUser */
#include "DNA_node_types.h" /* for bNodeInstanceKey */
#include "DNA_outliner_types.h" /* for TreeStoreElem */
#include "DNA_sequence_types.h" /* SequencerScopes */
#include "DNA_vec_types.h"
/* Hum ... Not really nice... but needed for spacebuts. */
#include "DNA_view2d_types.h"
@ -67,9 +66,15 @@ namespace blender::ed::outliner {
struct SpaceOutliner_Runtime;
} // namespace blender::ed::outliner
using SpaceOutliner_Runtime = blender::ed::outliner::SpaceOutliner_Runtime;
namespace blender::ed::seq {
struct SpaceSeq_Runtime;
} // namespace blender::ed::seq
using SpaceSeq_Runtime = blender::ed::seq::SpaceSeq_Runtime;
#else
typedef struct SpaceNode_Runtime SpaceNode_Runtime;
typedef struct SpaceOutliner_Runtime SpaceOutliner_Runtime;
typedef struct SpaceSeq_Runtime SpaceSeq_Runtime;
#endif
/** Defined in `file_intern.hh`. */
@ -631,15 +636,6 @@ typedef enum eSpaceSeq_SequencerTimelineOverlay_Flag {
SEQ_TIMELINE_SHOW_GRID = (1 << 18),
} eSpaceSeq_SequencerTimelineOverlay_Flag;
typedef struct SpaceSeqRuntime {
/** Required for Thumbnail job start condition. */
struct rctf last_thumbnail_area;
/** Stores lists of most recently displayed thumbnails. */
struct GHash *last_displayed_thumbnails;
int rename_channel_index;
float timeline_clamp_custom_range;
} SpaceSeqRuntime;
/** Sequencer. */
typedef struct SpaceSeq {
SpaceLink *next, *prev;
@ -678,8 +674,6 @@ typedef struct SpaceSeq {
/** Grease-pencil data. */
struct bGPdata *gpd;
/** Different scoped displayed in space. */
struct SequencerScopes scopes;
struct SequencerPreviewOverlay preview_overlay;
struct SequencerTimelineOverlay timeline_overlay;
@ -687,7 +681,7 @@ typedef struct SpaceSeq {
char multiview_eye;
char _pad2[7];
SpaceSeqRuntime runtime;
SpaceSeq_Runtime *runtime;
} SpaceSeq;
/** #SpaceSeq.mainb */

View File

@ -12,6 +12,7 @@
#include "DNA_brush_types.h"
#include "DNA_curve_types.h"
#include "DNA_scene_types.h"
#include "DNA_sequence_types.h"
#include "DNA_space_types.h"
#include "DNA_userdef_types.h"
#include "DNA_view3d_types.h"

View File

@ -13,6 +13,7 @@ struct Main;
struct Scene;
struct Sequence;
struct bSound;
struct SequenceModifierData;
struct SequencerSoundEqualizer;
struct SoundModifierWorkerInfo;
struct BlendWriter;

View File

@ -54,6 +54,7 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_sequence_types.h"
#include "DNA_space_types.h"
#include "DNA_userdef_types.h"
#include "DNA_windowmanager_types.h"