|
|
|
|
@@ -31,6 +31,7 @@
|
|
|
|
|
#include "BKE_context.hh"
|
|
|
|
|
#include "BKE_global.hh"
|
|
|
|
|
#include "BKE_scene.hh"
|
|
|
|
|
#include "BKE_screen.hh"
|
|
|
|
|
|
|
|
|
|
#include "IMB_colormanagement.hh"
|
|
|
|
|
#include "IMB_imbuf.hh"
|
|
|
|
|
@@ -49,6 +50,7 @@
|
|
|
|
|
#include "ED_sequencer.hh"
|
|
|
|
|
#include "ED_space_api.hh"
|
|
|
|
|
#include "ED_util.hh"
|
|
|
|
|
#include "ED_view3d.hh"
|
|
|
|
|
|
|
|
|
|
#include "BIF_glutil.hh"
|
|
|
|
|
|
|
|
|
|
@@ -75,7 +77,6 @@
|
|
|
|
|
#include "sequencer_scopes.hh"
|
|
|
|
|
|
|
|
|
|
namespace blender::ed::vse {
|
|
|
|
|
|
|
|
|
|
static Strip *special_seq_update = nullptr;
|
|
|
|
|
|
|
|
|
|
void sequencer_special_update_set(Strip *strip)
|
|
|
|
|
@@ -177,15 +178,15 @@ ImBuf *sequencer_ibuf_get(const bContext *C, const int timeline_frame, const cha
|
|
|
|
|
return ibuf;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static ImBuf *sequencer_make_scope(Scene *scene,
|
|
|
|
|
ImBuf *ibuf,
|
|
|
|
|
static ImBuf *sequencer_make_scope(const ColorManagedViewSettings &view_settings,
|
|
|
|
|
const ColorManagedDisplaySettings &display_settings,
|
|
|
|
|
const ImBuf &ibuf,
|
|
|
|
|
ImBuf *(*make_scope_fn)(const ImBuf *ibuf))
|
|
|
|
|
{
|
|
|
|
|
ImBuf *display_ibuf = IMB_dupImBuf(ibuf);
|
|
|
|
|
ImBuf *display_ibuf = IMB_dupImBuf(&ibuf);
|
|
|
|
|
ImBuf *scope;
|
|
|
|
|
|
|
|
|
|
IMB_colormanagement_imbuf_make_display_space(
|
|
|
|
|
display_ibuf, &scene->view_settings, &scene->display_settings);
|
|
|
|
|
IMB_colormanagement_imbuf_make_display_space(display_ibuf, &view_settings, &display_settings);
|
|
|
|
|
|
|
|
|
|
scope = make_scope_fn(display_ibuf);
|
|
|
|
|
|
|
|
|
|
@@ -194,12 +195,12 @@ static ImBuf *sequencer_make_scope(Scene *scene,
|
|
|
|
|
return scope;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void sequencer_display_size(Scene *scene, float r_viewrect[2])
|
|
|
|
|
static void sequencer_display_size(const RenderData &render_data, float r_viewrect[2])
|
|
|
|
|
{
|
|
|
|
|
r_viewrect[0] = float(scene->r.xsch);
|
|
|
|
|
r_viewrect[1] = float(scene->r.ysch);
|
|
|
|
|
r_viewrect[0] = float(render_data.xsch);
|
|
|
|
|
r_viewrect[1] = float(render_data.ysch);
|
|
|
|
|
|
|
|
|
|
r_viewrect[0] *= scene->r.xasp / scene->r.yasp;
|
|
|
|
|
r_viewrect[0] *= render_data.xasp / render_data.yasp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void sequencer_draw_gpencil_overlay(const bContext *C)
|
|
|
|
|
@@ -217,14 +218,14 @@ static void sequencer_draw_gpencil_overlay(const bContext *C)
|
|
|
|
|
/**
|
|
|
|
|
* Draw content and safety borders.
|
|
|
|
|
*/
|
|
|
|
|
static void sequencer_draw_borders_overlay(const SpaceSeq *sseq,
|
|
|
|
|
const View2D *v2d,
|
|
|
|
|
static void sequencer_draw_borders_overlay(const SpaceSeq &sseq,
|
|
|
|
|
const View2D &v2d,
|
|
|
|
|
const Scene *scene)
|
|
|
|
|
{
|
|
|
|
|
float x1 = v2d->tot.xmin;
|
|
|
|
|
float y1 = v2d->tot.ymin;
|
|
|
|
|
float x2 = v2d->tot.xmax;
|
|
|
|
|
float y2 = v2d->tot.ymax;
|
|
|
|
|
const float x1 = v2d.tot.xmin;
|
|
|
|
|
const float y1 = v2d.tot.ymin;
|
|
|
|
|
const float x2 = v2d.tot.xmax;
|
|
|
|
|
const float y2 = v2d.tot.ymax;
|
|
|
|
|
|
|
|
|
|
GPU_line_width(1.0f);
|
|
|
|
|
|
|
|
|
|
@@ -246,7 +247,7 @@ static void sequencer_draw_borders_overlay(const SpaceSeq *sseq,
|
|
|
|
|
imm_draw_box_wire_2d(shdr_pos, x1 - 0.5f, y1 - 0.5f, x2 + 0.5f, y2 + 0.5f);
|
|
|
|
|
|
|
|
|
|
/* Draw safety border. */
|
|
|
|
|
if (sseq->preview_overlay.flag & SEQ_PREVIEW_SHOW_SAFE_MARGINS) {
|
|
|
|
|
if (sseq.preview_overlay.flag & SEQ_PREVIEW_SHOW_SAFE_MARGINS) {
|
|
|
|
|
immUniformThemeColorBlend(TH_VIEW_OVERLAY, TH_BACK, 0.25f);
|
|
|
|
|
rctf rect;
|
|
|
|
|
rect.xmin = x1;
|
|
|
|
|
@@ -255,7 +256,7 @@ static void sequencer_draw_borders_overlay(const SpaceSeq *sseq,
|
|
|
|
|
rect.ymax = y2;
|
|
|
|
|
UI_draw_safe_areas(shdr_pos, &rect, scene->safe_areas.title, scene->safe_areas.action);
|
|
|
|
|
|
|
|
|
|
if (sseq->preview_overlay.flag & SEQ_PREVIEW_SHOW_SAFE_CENTER) {
|
|
|
|
|
if (sseq.preview_overlay.flag & SEQ_PREVIEW_SHOW_SAFE_CENTER) {
|
|
|
|
|
|
|
|
|
|
UI_draw_safe_areas(
|
|
|
|
|
shdr_pos, &rect, scene->safe_areas.title_center, scene->safe_areas.action_center);
|
|
|
|
|
@@ -309,73 +310,6 @@ static void seq_prefetch_wm_notify(const bContext *C, Scene *scene)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void *sequencer_OCIO_transform_ibuf(const bContext *C,
|
|
|
|
|
ImBuf *ibuf,
|
|
|
|
|
bool *r_glsl_used,
|
|
|
|
|
eGPUTextureFormat *r_format,
|
|
|
|
|
eGPUDataFormat *r_data,
|
|
|
|
|
void **r_buffer_cache_handle)
|
|
|
|
|
{
|
|
|
|
|
void *display_buffer;
|
|
|
|
|
bool force_fallback = false;
|
|
|
|
|
*r_glsl_used = false;
|
|
|
|
|
force_fallback |= (ED_draw_imbuf_method(ibuf) != IMAGE_DRAW_METHOD_GLSL);
|
|
|
|
|
force_fallback |= (ibuf->dither != 0.0f);
|
|
|
|
|
|
|
|
|
|
/* Default */
|
|
|
|
|
*r_format = GPU_RGBA8;
|
|
|
|
|
*r_data = GPU_DATA_UBYTE;
|
|
|
|
|
|
|
|
|
|
/* Fallback to CPU based color space conversion. */
|
|
|
|
|
if (force_fallback) {
|
|
|
|
|
*r_glsl_used = false;
|
|
|
|
|
display_buffer = nullptr;
|
|
|
|
|
}
|
|
|
|
|
else if (ibuf->float_buffer.data) {
|
|
|
|
|
display_buffer = ibuf->float_buffer.data;
|
|
|
|
|
|
|
|
|
|
*r_data = GPU_DATA_FLOAT;
|
|
|
|
|
if (ibuf->channels == 4) {
|
|
|
|
|
*r_format = GPU_RGBA32F;
|
|
|
|
|
}
|
|
|
|
|
else if (ibuf->channels == 3) {
|
|
|
|
|
/* Alpha is implicitly 1. */
|
|
|
|
|
*r_format = GPU_RGB32F;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
BLI_assert_msg(0, "Incompatible number of channels for float buffer in sequencer");
|
|
|
|
|
*r_format = GPU_RGBA32F;
|
|
|
|
|
display_buffer = nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ibuf->float_buffer.colorspace) {
|
|
|
|
|
*r_glsl_used = IMB_colormanagement_setup_glsl_draw_from_space_ctx(
|
|
|
|
|
C, ibuf->float_buffer.colorspace, ibuf->dither, true);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
*r_glsl_used = IMB_colormanagement_setup_glsl_draw_ctx(C, ibuf->dither, true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (ibuf->byte_buffer.data) {
|
|
|
|
|
display_buffer = ibuf->byte_buffer.data;
|
|
|
|
|
|
|
|
|
|
*r_glsl_used = IMB_colormanagement_setup_glsl_draw_from_space_ctx(
|
|
|
|
|
C, ibuf->byte_buffer.colorspace, ibuf->dither, false);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
display_buffer = nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If we need to fallback to CPU based display transform, do that here. */
|
|
|
|
|
if ((ibuf->byte_buffer.data || ibuf->float_buffer.data) && !*r_glsl_used) {
|
|
|
|
|
display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, r_buffer_cache_handle);
|
|
|
|
|
*r_format = GPU_RGBA8;
|
|
|
|
|
*r_data = GPU_DATA_UBYTE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return display_buffer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void sequencer_stop_running_jobs(const bContext *C, Scene *scene)
|
|
|
|
|
{
|
|
|
|
|
if (G.is_rendering == false && (scene->r.seq_prev_type) == OB_RENDER) {
|
|
|
|
|
@@ -394,102 +328,87 @@ static void sequencer_preview_clear()
|
|
|
|
|
UI_ThemeClearColor(TH_SEQ_PREVIEW);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void sequencer_preview_get_rect(
|
|
|
|
|
rctf *preview, Scene *scene, ARegion *region, SpaceSeq *sseq, bool draw_overlay)
|
|
|
|
|
/* Semantic utility to get a rectangle with positions that correspond to a full frame drawn in the
|
|
|
|
|
* preview region. */
|
|
|
|
|
static rctf preview_get_full_position(const ARegion ®ion)
|
|
|
|
|
{
|
|
|
|
|
View2D *v2d = ®ion->v2d;
|
|
|
|
|
float viewrect[2];
|
|
|
|
|
|
|
|
|
|
sequencer_display_size(scene, viewrect);
|
|
|
|
|
BLI_rctf_init(preview, -1.0f, 1.0f, -1.0f, 1.0f);
|
|
|
|
|
|
|
|
|
|
if (draw_overlay && (sseq->overlay_frame_type == SEQ_OVERLAY_FRAME_TYPE_RECT)) {
|
|
|
|
|
preview->xmax = v2d->tot.xmin +
|
|
|
|
|
(fabsf(BLI_rctf_size_x(&v2d->tot)) * scene->ed->overlay_frame_rect.xmax);
|
|
|
|
|
preview->xmin = v2d->tot.xmin +
|
|
|
|
|
(fabsf(BLI_rctf_size_x(&v2d->tot)) * scene->ed->overlay_frame_rect.xmin);
|
|
|
|
|
preview->ymax = v2d->tot.ymin +
|
|
|
|
|
(fabsf(BLI_rctf_size_y(&v2d->tot)) * scene->ed->overlay_frame_rect.ymax);
|
|
|
|
|
preview->ymin = v2d->tot.ymin +
|
|
|
|
|
(fabsf(BLI_rctf_size_y(&v2d->tot)) * scene->ed->overlay_frame_rect.ymin);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
*preview = v2d->tot;
|
|
|
|
|
}
|
|
|
|
|
return region.v2d.tot;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void sequencer_draw_display_buffer(const bContext *C,
|
|
|
|
|
Scene *scene,
|
|
|
|
|
ARegion *region,
|
|
|
|
|
SpaceSeq *sseq,
|
|
|
|
|
ImBuf *ibuf,
|
|
|
|
|
bool draw_overlay)
|
|
|
|
|
/* Semantic utility to generate rectangle with UV coordinates that cover an entire 0 .. 1
|
|
|
|
|
* rectangle. */
|
|
|
|
|
static rctf preview_get_full_texture_coord()
|
|
|
|
|
{
|
|
|
|
|
void *buffer_cache_handle = nullptr;
|
|
|
|
|
|
|
|
|
|
if (sseq->mainb == SEQ_DRAW_IMG_IMBUF && sseq->flag & SEQ_USE_ALPHA) {
|
|
|
|
|
GPU_blend(GPU_BLEND_ALPHA);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Format needs to be created prior to any #immBindShader call.
|
|
|
|
|
* Do it here because OCIO binds its own shader. */
|
|
|
|
|
eGPUTextureFormat format;
|
|
|
|
|
eGPUDataFormat data;
|
|
|
|
|
bool glsl_used = false;
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
void *display_buffer = sequencer_OCIO_transform_ibuf(
|
|
|
|
|
C, ibuf, &glsl_used, &format, &data, &buffer_cache_handle);
|
|
|
|
|
|
|
|
|
|
eGPUTextureUsage usage = GPU_TEXTURE_USAGE_SHADER_READ | GPU_TEXTURE_USAGE_ATTACHMENT;
|
|
|
|
|
GPUTexture *texture = GPU_texture_create_2d(
|
|
|
|
|
"seq_display_buf", ibuf->x, ibuf->y, 1, format, usage, nullptr);
|
|
|
|
|
GPU_texture_update(texture, data, display_buffer);
|
|
|
|
|
GPU_texture_filter_mode(texture, false);
|
|
|
|
|
|
|
|
|
|
GPU_texture_bind(texture, 0);
|
|
|
|
|
|
|
|
|
|
if (!glsl_used) {
|
|
|
|
|
immBindBuiltinProgram(GPU_SHADER_3D_IMAGE_COLOR);
|
|
|
|
|
immUniformColor3f(1.0f, 1.0f, 1.0f);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rctf preview;
|
|
|
|
|
rctf canvas;
|
|
|
|
|
sequencer_preview_get_rect(&preview, scene, region, sseq, draw_overlay);
|
|
|
|
|
|
|
|
|
|
if (draw_overlay && (sseq->overlay_frame_type == SEQ_OVERLAY_FRAME_TYPE_RECT)) {
|
|
|
|
|
canvas = scene->ed->overlay_frame_rect;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
BLI_rctf_init(&canvas, 0.0f, 1.0f, 0.0f, 1.0f);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
immRectf_with_texco(pos, texCoord, preview, canvas);
|
|
|
|
|
|
|
|
|
|
GPU_texture_unbind(texture);
|
|
|
|
|
GPU_texture_free(texture);
|
|
|
|
|
|
|
|
|
|
if (!glsl_used) {
|
|
|
|
|
immUnbindProgram();
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
IMB_colormanagement_finish_glsl_draw();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (buffer_cache_handle) {
|
|
|
|
|
IMB_display_buffer_release(buffer_cache_handle);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (sseq->mainb == SEQ_DRAW_IMG_IMBUF && sseq->flag & SEQ_USE_ALPHA) {
|
|
|
|
|
GPU_blend(GPU_BLEND_NONE);
|
|
|
|
|
}
|
|
|
|
|
rctf texture_coord;
|
|
|
|
|
BLI_rctf_init(&texture_coord, 0.0f, 1.0f, 0.0f, 1.0f);
|
|
|
|
|
return texture_coord;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void draw_histogram(ARegion *region,
|
|
|
|
|
/* Get rectangle positions within preview region that are to be used to draw reference frame.
|
|
|
|
|
*
|
|
|
|
|
* If the frame overlay is set to RECTANGLE this function returns coordinates of the rectangle
|
|
|
|
|
* where partial reference frame is to be drawn.
|
|
|
|
|
*
|
|
|
|
|
* If the frame overlay is set to REFERENCE this function returns full-frame rectangle, same as
|
|
|
|
|
* preview_get_full_position().
|
|
|
|
|
*
|
|
|
|
|
* If the frame overlay is set to REFERENCE or is disabled the return value is valid but
|
|
|
|
|
* corresponds to an undefined state.
|
|
|
|
|
*/
|
|
|
|
|
static rctf preview_get_reference_position(const SpaceSeq &space_sequencer,
|
|
|
|
|
const Editing &editing,
|
|
|
|
|
const ARegion ®ion)
|
|
|
|
|
{
|
|
|
|
|
const View2D &v2d = region.v2d;
|
|
|
|
|
|
|
|
|
|
BLI_assert(ELEM(space_sequencer.overlay_frame_type,
|
|
|
|
|
SEQ_OVERLAY_FRAME_TYPE_RECT,
|
|
|
|
|
SEQ_OVERLAY_FRAME_TYPE_REFERENCE));
|
|
|
|
|
|
|
|
|
|
if (space_sequencer.overlay_frame_type == SEQ_OVERLAY_FRAME_TYPE_RECT) {
|
|
|
|
|
rctf position;
|
|
|
|
|
const float xmin = v2d.tot.xmin;
|
|
|
|
|
const float ymin = v2d.tot.ymin;
|
|
|
|
|
|
|
|
|
|
const float width = BLI_rctf_size_x(&v2d.tot);
|
|
|
|
|
const float height = BLI_rctf_size_y(&v2d.tot);
|
|
|
|
|
|
|
|
|
|
position.xmax = xmin + width * editing.overlay_frame_rect.xmax;
|
|
|
|
|
position.xmin = xmin + width * editing.overlay_frame_rect.xmin;
|
|
|
|
|
position.ymax = ymin + height * editing.overlay_frame_rect.ymax;
|
|
|
|
|
position.ymin = ymin + height * editing.overlay_frame_rect.ymin;
|
|
|
|
|
|
|
|
|
|
return position;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return v2d.tot;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Return rectangle with UV coordinates that are to be used to draw reference frame.
|
|
|
|
|
*
|
|
|
|
|
* If the frame overlay is set to rectangle the return value contains vUV coordinates of the
|
|
|
|
|
* rectangle within the reference frame.
|
|
|
|
|
*
|
|
|
|
|
* If the frame overlay is set to REFERENCE this function returns full-frame UV rectangle, same as
|
|
|
|
|
* preview_get_full_texture_coord().
|
|
|
|
|
*
|
|
|
|
|
* If the frame overlay is set to REFERENCE or is disabled the return value is valid but
|
|
|
|
|
* corresponds to an undefined state.
|
|
|
|
|
*/
|
|
|
|
|
static rctf preview_get_reference_texture_coord(const SpaceSeq &space_sequencer,
|
|
|
|
|
const Editing &editing)
|
|
|
|
|
{
|
|
|
|
|
if (space_sequencer.overlay_frame_type == SEQ_OVERLAY_FRAME_TYPE_RECT) {
|
|
|
|
|
return editing.overlay_frame_rect;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rctf texture_coord;
|
|
|
|
|
BLI_rctf_init(&texture_coord, 0.0f, 1.0f, 0.0f, 1.0f);
|
|
|
|
|
|
|
|
|
|
return texture_coord;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void draw_histogram(ARegion ®ion,
|
|
|
|
|
const ScopeHistogram &hist,
|
|
|
|
|
SeqQuadsBatch &quads,
|
|
|
|
|
const rctf &area)
|
|
|
|
|
@@ -510,9 +429,9 @@ static void draw_histogram(ARegion *region,
|
|
|
|
|
grid_x_1 = area.xmin + (area.xmax - area.xmin) * ratio_1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
View2D *v2d = ®ion->v2d;
|
|
|
|
|
View2D &v2d = region.v2d;
|
|
|
|
|
float text_scale_x, text_scale_y;
|
|
|
|
|
UI_view2d_scale_get_inverse(v2d, &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;
|
|
|
|
|
@@ -528,7 +447,7 @@ static void draw_histogram(ARegion *region,
|
|
|
|
|
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);
|
|
|
|
|
&v2d, x - text_width / 2, area.ymax - text_height * 1.3f, buf, buf_len, col_grid);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Border. */
|
|
|
|
|
@@ -562,7 +481,7 @@ static void draw_histogram(ARegion *region,
|
|
|
|
|
quads.draw();
|
|
|
|
|
GPU_blend(GPU_BLEND_ALPHA);
|
|
|
|
|
|
|
|
|
|
UI_view2d_text_cache_draw(region);
|
|
|
|
|
UI_view2d_text_cache_draw(®ion);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static blender::float2 rgb_to_uv_scaled(const blender::float3 &rgb)
|
|
|
|
|
@@ -754,15 +673,14 @@ static void draw_vectorscope_graticule(ARegion *region, SeqQuadsBatch &quads, co
|
|
|
|
|
UI_view2d_text_cache_draw(region);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void sequencer_draw_scopes(Scene *scene, ARegion *region, SpaceSeq *sseq)
|
|
|
|
|
static void sequencer_draw_scopes(const SpaceSeq &space_sequencer, ARegion ®ion)
|
|
|
|
|
{
|
|
|
|
|
/* Figure out draw coordinates. */
|
|
|
|
|
rctf preview;
|
|
|
|
|
sequencer_preview_get_rect(&preview, scene, region, sseq, false);
|
|
|
|
|
const rctf preview = preview_get_full_position(region);
|
|
|
|
|
|
|
|
|
|
rctf uv;
|
|
|
|
|
BLI_rctf_init(&uv, 0.0f, 1.0f, 0.0f, 1.0f);
|
|
|
|
|
const bool keep_aspect = sseq->mainb == SEQ_DRAW_IMG_VECTORSCOPE;
|
|
|
|
|
const bool keep_aspect = space_sequencer.mainb == SEQ_DRAW_IMG_VECTORSCOPE;
|
|
|
|
|
float vecscope_aspect = 1.0f;
|
|
|
|
|
if (keep_aspect) {
|
|
|
|
|
float width = std::max(BLI_rctf_size_x(&preview), 0.1f);
|
|
|
|
|
@@ -777,12 +695,13 @@ static void sequencer_draw_scopes(Scene *scene, ARegion *region, SpaceSeq *sseq)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SeqQuadsBatch quads;
|
|
|
|
|
SeqScopes *scopes = &sseq->runtime->scopes;
|
|
|
|
|
const SeqScopes *scopes = &space_sequencer.runtime->scopes;
|
|
|
|
|
|
|
|
|
|
bool use_blend = sseq->mainb == SEQ_DRAW_IMG_IMBUF && sseq->flag & SEQ_USE_ALPHA;
|
|
|
|
|
bool use_blend = space_sequencer.mainb == SEQ_DRAW_IMG_IMBUF &&
|
|
|
|
|
space_sequencer.flag & SEQ_USE_ALPHA;
|
|
|
|
|
|
|
|
|
|
/* Draw black rectangle over scopes area. */
|
|
|
|
|
if (sseq->mainb != SEQ_DRAW_IMG_IMBUF) {
|
|
|
|
|
if (space_sequencer.mainb != SEQ_DRAW_IMG_IMBUF) {
|
|
|
|
|
GPU_blend(GPU_BLEND_NONE);
|
|
|
|
|
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
|
|
|
|
uchar black[4] = {0, 0, 0, 255};
|
|
|
|
|
@@ -794,16 +713,16 @@ static void sequencer_draw_scopes(Scene *scene, ARegion *region, SpaceSeq *sseq)
|
|
|
|
|
|
|
|
|
|
/* Draw scope image if there is one. */
|
|
|
|
|
ImBuf *scope_image = nullptr;
|
|
|
|
|
if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
|
|
|
|
|
if (space_sequencer.mainb == SEQ_DRAW_IMG_IMBUF) {
|
|
|
|
|
scope_image = scopes->zebra_ibuf;
|
|
|
|
|
}
|
|
|
|
|
else if (sseq->mainb == SEQ_DRAW_IMG_WAVEFORM) {
|
|
|
|
|
else if (space_sequencer.mainb == SEQ_DRAW_IMG_WAVEFORM) {
|
|
|
|
|
scope_image = scopes->waveform_ibuf;
|
|
|
|
|
}
|
|
|
|
|
else if (sseq->mainb == SEQ_DRAW_IMG_VECTORSCOPE) {
|
|
|
|
|
else if (space_sequencer.mainb == SEQ_DRAW_IMG_VECTORSCOPE) {
|
|
|
|
|
scope_image = scopes->vector_ibuf;
|
|
|
|
|
}
|
|
|
|
|
else if (sseq->mainb == SEQ_DRAW_IMG_RGBPARADE) {
|
|
|
|
|
else if (space_sequencer.mainb == SEQ_DRAW_IMG_RGBPARADE) {
|
|
|
|
|
scope_image = scopes->sep_waveform_ibuf;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -856,16 +775,16 @@ static void sequencer_draw_scopes(Scene *scene, ARegion *region, SpaceSeq *sseq)
|
|
|
|
|
immUnbindProgram();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (sseq->mainb == SEQ_DRAW_IMG_HISTOGRAM) {
|
|
|
|
|
if (space_sequencer.mainb == SEQ_DRAW_IMG_HISTOGRAM) {
|
|
|
|
|
draw_histogram(region, scopes->histogram, quads, preview);
|
|
|
|
|
}
|
|
|
|
|
if (ELEM(sseq->mainb, SEQ_DRAW_IMG_WAVEFORM, SEQ_DRAW_IMG_RGBPARADE)) {
|
|
|
|
|
if (ELEM(space_sequencer.mainb, SEQ_DRAW_IMG_WAVEFORM, SEQ_DRAW_IMG_RGBPARADE)) {
|
|
|
|
|
use_blend = true;
|
|
|
|
|
draw_waveform_graticule(region, quads, preview);
|
|
|
|
|
draw_waveform_graticule(®ion, quads, preview);
|
|
|
|
|
}
|
|
|
|
|
if (sseq->mainb == SEQ_DRAW_IMG_VECTORSCOPE) {
|
|
|
|
|
if (space_sequencer.mainb == SEQ_DRAW_IMG_VECTORSCOPE) {
|
|
|
|
|
use_blend = true;
|
|
|
|
|
draw_vectorscope_graticule(region, quads, preview);
|
|
|
|
|
draw_vectorscope_graticule(®ion, quads, preview);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
quads.draw();
|
|
|
|
|
@@ -875,76 +794,81 @@ static void sequencer_draw_scopes(Scene *scene, ARegion *region, SpaceSeq *sseq)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool sequencer_calc_scopes(Scene *scene, SpaceSeq *sseq, ImBuf *ibuf)
|
|
|
|
|
static bool sequencer_calc_scopes(const SpaceSeq &space_sequencer,
|
|
|
|
|
const ColorManagedViewSettings &view_settings,
|
|
|
|
|
const ColorManagedDisplaySettings &display_settings,
|
|
|
|
|
const ImBuf &ibuf)
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
if (sseq->mainb == SEQ_DRAW_IMG_IMBUF && sseq->zebra == 0) {
|
|
|
|
|
if (space_sequencer.mainb == SEQ_DRAW_IMG_IMBUF && space_sequencer.zebra == 0) {
|
|
|
|
|
return false; /* Not drawing any scopes. */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SeqScopes *scopes = &sseq->runtime->scopes;
|
|
|
|
|
if (scopes->reference_ibuf != ibuf) {
|
|
|
|
|
SeqScopes *scopes = &space_sequencer.runtime->scopes;
|
|
|
|
|
if (scopes->reference_ibuf != &ibuf) {
|
|
|
|
|
scopes->cleanup();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (sseq->mainb) {
|
|
|
|
|
switch (space_sequencer.mainb) {
|
|
|
|
|
case SEQ_DRAW_IMG_IMBUF:
|
|
|
|
|
if (!scopes->zebra_ibuf) {
|
|
|
|
|
|
|
|
|
|
if (ibuf->float_buffer.data) {
|
|
|
|
|
ImBuf *display_ibuf = IMB_dupImBuf(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);
|
|
|
|
|
display_ibuf, &view_settings, &display_settings);
|
|
|
|
|
scopes->zebra_ibuf = make_zebra_view_from_ibuf(display_ibuf, space_sequencer.zebra);
|
|
|
|
|
IMB_freeImBuf(display_ibuf);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
scopes->zebra_ibuf = make_zebra_view_from_ibuf(ibuf, sseq->zebra);
|
|
|
|
|
scopes->zebra_ibuf = make_zebra_view_from_ibuf(&ibuf, space_sequencer.zebra);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case SEQ_DRAW_IMG_WAVEFORM:
|
|
|
|
|
if (!scopes->waveform_ibuf) {
|
|
|
|
|
scopes->waveform_ibuf = sequencer_make_scope(scene, ibuf, make_waveform_view_from_ibuf);
|
|
|
|
|
scopes->waveform_ibuf = sequencer_make_scope(
|
|
|
|
|
view_settings, display_settings, 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);
|
|
|
|
|
scopes->vector_ibuf = sequencer_make_scope(
|
|
|
|
|
view_settings, display_settings, ibuf, make_vectorscope_view_from_ibuf);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case SEQ_DRAW_IMG_HISTOGRAM: {
|
|
|
|
|
ImBuf *display_ibuf = IMB_dupImBuf(ibuf);
|
|
|
|
|
ImBuf *display_ibuf = IMB_dupImBuf(&ibuf);
|
|
|
|
|
IMB_colormanagement_imbuf_make_display_space(
|
|
|
|
|
display_ibuf, &scene->view_settings, &scene->display_settings);
|
|
|
|
|
display_ibuf, &view_settings, &display_settings);
|
|
|
|
|
scopes->histogram.calc_from_ibuf(display_ibuf);
|
|
|
|
|
IMB_freeImBuf(display_ibuf);
|
|
|
|
|
} break;
|
|
|
|
|
case SEQ_DRAW_IMG_RGBPARADE:
|
|
|
|
|
if (!scopes->sep_waveform_ibuf) {
|
|
|
|
|
scopes->sep_waveform_ibuf = sequencer_make_scope(
|
|
|
|
|
scene, ibuf, make_sep_waveform_view_from_ibuf);
|
|
|
|
|
view_settings, display_settings, ibuf, make_sep_waveform_view_from_ibuf);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default: /* Future files might have scopes we don't know about. */
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
scopes->reference_ibuf = ibuf;
|
|
|
|
|
scopes->reference_ibuf = &ibuf;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool sequencer_draw_get_transform_preview(SpaceSeq *sseq, Scene *scene)
|
|
|
|
|
bool sequencer_draw_get_transform_preview(const SpaceSeq &sseq, const Scene &scene)
|
|
|
|
|
{
|
|
|
|
|
Strip *last_seq = seq::select_active_get(scene);
|
|
|
|
|
Strip *last_seq = seq::select_active_get(&scene);
|
|
|
|
|
if (last_seq == nullptr) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (G.moving & G_TRANSFORM_SEQ) && (last_seq->flag & SELECT) &&
|
|
|
|
|
((last_seq->flag & SEQ_LEFTSEL) || (last_seq->flag & SEQ_RIGHTSEL)) &&
|
|
|
|
|
(sseq->draw_flag & SEQ_DRAW_TRANSFORM_PREVIEW);
|
|
|
|
|
(sseq.draw_flag & SEQ_DRAW_TRANSFORM_PREVIEW);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int sequencer_draw_get_transform_preview_frame(Scene *scene)
|
|
|
|
|
int sequencer_draw_get_transform_preview_frame(const Scene *scene)
|
|
|
|
|
{
|
|
|
|
|
Strip *last_seq = seq::select_active_get(scene);
|
|
|
|
|
/* #sequencer_draw_get_transform_preview must already have been called. */
|
|
|
|
|
@@ -1214,112 +1138,632 @@ static void text_edit_draw(const bContext *C)
|
|
|
|
|
text_edit_draw_box(C, strip, pos);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void sequencer_draw_preview(const bContext *C,
|
|
|
|
|
Scene *scene,
|
|
|
|
|
ARegion *region,
|
|
|
|
|
SpaceSeq *sseq,
|
|
|
|
|
int timeline_frame,
|
|
|
|
|
int offset,
|
|
|
|
|
bool draw_overlay)
|
|
|
|
|
/* Draw empty preview region.
|
|
|
|
|
* The entire region is cleared with the TH_SEQ_PREVIEW color.
|
|
|
|
|
*
|
|
|
|
|
* Used in cases when there is no editing, or when the display is set to NONE. */
|
|
|
|
|
static void sequencer_preview_draw_empty(ARegion ®ion)
|
|
|
|
|
{
|
|
|
|
|
View2D *v2d = ®ion->v2d;
|
|
|
|
|
ImBuf *ibuf = nullptr;
|
|
|
|
|
float viewrect[2];
|
|
|
|
|
const bool show_imbuf = check_show_imbuf(*sseq);
|
|
|
|
|
const bool draw_gpencil = ((sseq->preview_overlay.flag & SEQ_PREVIEW_SHOW_GPENCIL) && sseq->gpd);
|
|
|
|
|
const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
|
|
|
|
|
GPUViewport *viewport = WM_draw_region_get_bound_viewport(®ion);
|
|
|
|
|
BLI_assert(viewport);
|
|
|
|
|
|
|
|
|
|
sequencer_stop_running_jobs(C, scene);
|
|
|
|
|
GPUFrameBuffer *overlay_fb = GPU_viewport_framebuffer_overlay_get(viewport);
|
|
|
|
|
GPU_framebuffer_bind_no_srgb(overlay_fb);
|
|
|
|
|
|
|
|
|
|
sequencer_preview_clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Begin drawing the sequence preview region.
|
|
|
|
|
* Initializes the drawing state which is common for color render and overlay drawing.
|
|
|
|
|
*
|
|
|
|
|
* Returns true if the region is to be drawn. Example is when it is not to be drawn is when there
|
|
|
|
|
* is ongoing offline rendering (to avoid possible threading conflict).
|
|
|
|
|
*
|
|
|
|
|
* If the function returns true preview_draw_end() is to be called after drawing is done. */
|
|
|
|
|
static bool preview_draw_begin(const bContext *C,
|
|
|
|
|
const RenderData &render_data,
|
|
|
|
|
const ColorManagedViewSettings &view_settings,
|
|
|
|
|
const ColorManagedDisplaySettings &display_settings,
|
|
|
|
|
ARegion ®ion)
|
|
|
|
|
{
|
|
|
|
|
sequencer_stop_running_jobs(C, CTX_data_scene(C));
|
|
|
|
|
if (G.is_rendering) {
|
|
|
|
|
return;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int preview_frame = timeline_frame;
|
|
|
|
|
if (sequencer_draw_get_transform_preview(sseq, scene)) {
|
|
|
|
|
preview_frame = sequencer_draw_get_transform_preview_frame(scene);
|
|
|
|
|
}
|
|
|
|
|
GPUViewport *viewport = WM_draw_region_get_bound_viewport(®ion);
|
|
|
|
|
BLI_assert(viewport);
|
|
|
|
|
|
|
|
|
|
/* Get image. */
|
|
|
|
|
ibuf = sequencer_ibuf_get(C, preview_frame + offset, names[sseq->multiview_eye]);
|
|
|
|
|
/* Configure color space used by the viewport.
|
|
|
|
|
* This also checks for HDR support and enables it for the viewport when found and needed. */
|
|
|
|
|
GPU_viewport_colorspace_set(
|
|
|
|
|
viewport, &view_settings, &display_settings, render_data.dither_intensity);
|
|
|
|
|
|
|
|
|
|
/* Setup off-screen buffers. */
|
|
|
|
|
GPUViewport *viewport = WM_draw_region_get_viewport(region);
|
|
|
|
|
GPUFrameBuffer *framebuffer_overlay = GPU_viewport_framebuffer_overlay_get(viewport);
|
|
|
|
|
GPU_framebuffer_bind_no_srgb(framebuffer_overlay);
|
|
|
|
|
GPU_depth_test(GPU_DEPTH_NONE);
|
|
|
|
|
|
|
|
|
|
if (sseq->render_size == SEQ_RENDER_SIZE_NONE) {
|
|
|
|
|
sequencer_preview_clear();
|
|
|
|
|
/* Setup view. */
|
|
|
|
|
View2D &v2d = region.v2d;
|
|
|
|
|
float viewrect[2];
|
|
|
|
|
sequencer_display_size(render_data, viewrect);
|
|
|
|
|
UI_view2d_totRect_set(&v2d, roundf(viewrect[0]), roundf(viewrect[1]));
|
|
|
|
|
UI_view2d_curRect_validate(&v2d);
|
|
|
|
|
UI_view2d_view_ortho(&v2d);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void preview_draw_end(const bContext *C)
|
|
|
|
|
{
|
|
|
|
|
UI_view2d_view_restore(C);
|
|
|
|
|
seq_prefetch_wm_notify(C, CTX_data_scene(C));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Configure current GPU state to draw on the color render frame-buffer of the viewport. */
|
|
|
|
|
static void preview_draw_color_render_begin(ARegion ®ion)
|
|
|
|
|
{
|
|
|
|
|
GPUViewport *viewport = WM_draw_region_get_bound_viewport(®ion);
|
|
|
|
|
BLI_assert(viewport);
|
|
|
|
|
|
|
|
|
|
GPUFrameBuffer *render_fb = GPU_viewport_framebuffer_render_get(viewport);
|
|
|
|
|
GPU_framebuffer_bind(render_fb);
|
|
|
|
|
|
|
|
|
|
float col[4] = {0, 0, 0, 0};
|
|
|
|
|
GPU_framebuffer_clear_color(render_fb, col);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Configure current GPU state to draw on the overlay frame-buffer of the viewport. */
|
|
|
|
|
static void preview_draw_overlay_begin(ARegion ®ion)
|
|
|
|
|
{
|
|
|
|
|
GPUViewport *viewport = WM_draw_region_get_bound_viewport(®ion);
|
|
|
|
|
BLI_assert(viewport);
|
|
|
|
|
|
|
|
|
|
GPUFrameBuffer *overlay_fb = GPU_viewport_framebuffer_overlay_get(viewport);
|
|
|
|
|
GPU_framebuffer_bind_no_srgb(overlay_fb);
|
|
|
|
|
|
|
|
|
|
sequencer_preview_clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Draw the given texture on the currently bound frame-buffer without any changes to its pixels
|
|
|
|
|
* colors.
|
|
|
|
|
*
|
|
|
|
|
* The position denotes coordinates of a rectangle used to display the texture.
|
|
|
|
|
* The texture_coord contains UV coordinates of the input texture which are mapped to the corners
|
|
|
|
|
* of the rectangle. */
|
|
|
|
|
void preview_draw_texture_simple(GPUTexture &texture,
|
|
|
|
|
const rctf &position,
|
|
|
|
|
const rctf &texture_coord)
|
|
|
|
|
{
|
|
|
|
|
GPUVertFormat *imm_format = immVertexFormat();
|
|
|
|
|
const uint pos = GPU_vertformat_attr_add(imm_format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
|
|
|
|
const uint tex_coord = 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);
|
|
|
|
|
|
|
|
|
|
GPU_texture_bind(&texture, 0);
|
|
|
|
|
|
|
|
|
|
immRectf_with_texco(pos, tex_coord, position, texture_coord);
|
|
|
|
|
|
|
|
|
|
GPU_texture_unbind(&texture);
|
|
|
|
|
immUnbindProgram();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Draw the given texture on the currently bound frame-buffer and convert its colors to linear
|
|
|
|
|
* space in the fragment shader. This makes it suitable to be further processed by a GPUViewport
|
|
|
|
|
*
|
|
|
|
|
* The position denotes coordinates of a rectangle used to display the texture.
|
|
|
|
|
* The texture_coord contains UV coordinates of the input texture which are mapped to the corners
|
|
|
|
|
* of the rectangle. */
|
|
|
|
|
void preview_draw_texture_to_linear(GPUTexture &texture,
|
|
|
|
|
const char *texture_colorspace_name,
|
|
|
|
|
const bool predivide,
|
|
|
|
|
const rctf &position,
|
|
|
|
|
const rctf &texture_coord)
|
|
|
|
|
{
|
|
|
|
|
GPUVertFormat *imm_format = immVertexFormat();
|
|
|
|
|
const uint pos = GPU_vertformat_attr_add(imm_format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
|
|
|
|
const uint tex_coord = GPU_vertformat_attr_add(
|
|
|
|
|
imm_format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
|
|
|
|
|
|
|
|
|
if (!IMB_colormanagement_setup_glsl_draw_to_scene_linear(texture_colorspace_name, predivide)) {
|
|
|
|
|
/* An error happened when configuring GPU side color space conversion. Return and allow the
|
|
|
|
|
* view to be black, so that it is obvious something went wrong and that a bug report is to
|
|
|
|
|
* be submitted.
|
|
|
|
|
*
|
|
|
|
|
* Note that fallback OCIO implementation is handled on a higher level. */
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Setup view. */
|
|
|
|
|
sequencer_display_size(scene, viewrect);
|
|
|
|
|
UI_view2d_totRect_set(v2d, roundf(viewrect[0]), roundf(viewrect[1]));
|
|
|
|
|
UI_view2d_curRect_validate(v2d);
|
|
|
|
|
UI_view2d_view_ortho(v2d);
|
|
|
|
|
GPU_texture_bind(&texture, 0);
|
|
|
|
|
|
|
|
|
|
/* Draw background. */
|
|
|
|
|
if (!draw_overlay || (sseq->overlay_frame_type == SEQ_OVERLAY_FRAME_TYPE_REFERENCE)) {
|
|
|
|
|
sequencer_preview_clear();
|
|
|
|
|
immRectf_with_texco(pos, tex_coord, position, texture_coord);
|
|
|
|
|
|
|
|
|
|
if (sseq->flag & SEQ_USE_ALPHA) {
|
|
|
|
|
imm_draw_box_checker_2d(v2d->tot.xmin, v2d->tot.ymin, v2d->tot.xmax, v2d->tot.ymax);
|
|
|
|
|
GPU_texture_unbind(&texture);
|
|
|
|
|
|
|
|
|
|
IMB_colormanagement_finish_glsl_draw();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Draw overlays for the currently displayed images in the preview. */
|
|
|
|
|
void preview_draw_all_image_overlays(const bContext *C,
|
|
|
|
|
const Scene *scene,
|
|
|
|
|
const Editing &editing,
|
|
|
|
|
const int timeline_frame)
|
|
|
|
|
{
|
|
|
|
|
ListBase *channels = seq::channels_displayed_get(&editing);
|
|
|
|
|
VectorSet strips = seq::query_rendered_strips(
|
|
|
|
|
scene, channels, editing.seqbasep, timeline_frame, 0);
|
|
|
|
|
Strip *active_seq = seq::select_active_get(scene);
|
|
|
|
|
for (Strip *strip : strips) {
|
|
|
|
|
/* TODO(sergey): Avoid having per-strip strip-independent checks. */
|
|
|
|
|
strip_draw_image_origin_and_outline(C, strip, strip == active_seq);
|
|
|
|
|
text_edit_draw(C);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool is_cursor_visible(const SpaceSeq &sseq)
|
|
|
|
|
{
|
|
|
|
|
if (G.moving & G_TRANSFORM_CURSOR) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((sseq.flag & SEQ_SHOW_OVERLAY) &&
|
|
|
|
|
(sseq.preview_overlay.flag & SEQ_PREVIEW_SHOW_2D_CURSOR) != 0)
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* We may want to move this into a more general location.
|
|
|
|
|
*/
|
|
|
|
|
static void draw_cursor_2d(const ARegion *region, const blender::float2 &cursor)
|
|
|
|
|
{
|
|
|
|
|
int co[2];
|
|
|
|
|
UI_view2d_view_to_region(®ion->v2d, cursor[0], cursor[1], &co[0], &co[1]);
|
|
|
|
|
|
|
|
|
|
/* Draw nice Anti Aliased cursor. */
|
|
|
|
|
GPU_blend(GPU_BLEND_ALPHA);
|
|
|
|
|
|
|
|
|
|
/* Draw lines */
|
|
|
|
|
float original_proj[4][4];
|
|
|
|
|
GPU_matrix_projection_get(original_proj);
|
|
|
|
|
GPU_matrix_push();
|
|
|
|
|
ED_region_pixelspace(region);
|
|
|
|
|
GPU_matrix_translate_2f(co[0] + 0.5f, co[1] + 0.5f);
|
|
|
|
|
GPU_matrix_scale_2f(U.widget_unit, U.widget_unit);
|
|
|
|
|
|
|
|
|
|
float viewport[4];
|
|
|
|
|
GPU_viewport_size_get_f(viewport);
|
|
|
|
|
|
|
|
|
|
GPUVertFormat *format = immVertexFormat();
|
|
|
|
|
struct {
|
|
|
|
|
uint pos, col;
|
|
|
|
|
} attr_id{};
|
|
|
|
|
attr_id.pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
|
|
|
|
attr_id.col = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
|
|
|
|
|
immBindBuiltinProgram(GPU_SHADER_3D_POLYLINE_FLAT_COLOR);
|
|
|
|
|
immUniform2fv("viewportSize", &viewport[2]);
|
|
|
|
|
immUniform1f("lineWidth", U.pixelsize);
|
|
|
|
|
|
|
|
|
|
const float f5 = 0.25f;
|
|
|
|
|
const float f10 = 0.5f;
|
|
|
|
|
const float f20 = 1.0f;
|
|
|
|
|
|
|
|
|
|
const float red[3] = {1.0f, 0.0f, 0.0f};
|
|
|
|
|
const float white[3] = {1.0f, 1.0f, 1.0f};
|
|
|
|
|
|
|
|
|
|
const int segments = 16;
|
|
|
|
|
immBegin(GPU_PRIM_LINE_STRIP, segments + 1);
|
|
|
|
|
for (int i = 0; i < segments + 1; i++) {
|
|
|
|
|
float angle = float(2 * M_PI) * (float(i) / float(segments));
|
|
|
|
|
float x = f10 * cosf(angle);
|
|
|
|
|
float y = f10 * sinf(angle);
|
|
|
|
|
|
|
|
|
|
immAttr3fv(attr_id.col, (i % 2 == 0) ? red : white);
|
|
|
|
|
immVertex2f(attr_id.pos, x, y);
|
|
|
|
|
}
|
|
|
|
|
immEnd();
|
|
|
|
|
|
|
|
|
|
float crosshair_color[3];
|
|
|
|
|
UI_GetThemeColor3fv(TH_VIEW_OVERLAY, crosshair_color);
|
|
|
|
|
|
|
|
|
|
immBegin(GPU_PRIM_LINES, 8);
|
|
|
|
|
immAttr3fv(attr_id.col, crosshair_color);
|
|
|
|
|
immVertex2f(attr_id.pos, -f20, 0);
|
|
|
|
|
immAttr3fv(attr_id.col, crosshair_color);
|
|
|
|
|
immVertex2f(attr_id.pos, -f5, 0);
|
|
|
|
|
|
|
|
|
|
immAttr3fv(attr_id.col, crosshair_color);
|
|
|
|
|
immVertex2f(attr_id.pos, +f20, 0);
|
|
|
|
|
immAttr3fv(attr_id.col, crosshair_color);
|
|
|
|
|
immVertex2f(attr_id.pos, +f5, 0);
|
|
|
|
|
|
|
|
|
|
immAttr3fv(attr_id.col, crosshair_color);
|
|
|
|
|
immVertex2f(attr_id.pos, 0, -f20);
|
|
|
|
|
immAttr3fv(attr_id.col, crosshair_color);
|
|
|
|
|
immVertex2f(attr_id.pos, 0, -f5);
|
|
|
|
|
|
|
|
|
|
immAttr3fv(attr_id.col, crosshair_color);
|
|
|
|
|
immVertex2f(attr_id.pos, 0, +f20);
|
|
|
|
|
immAttr3fv(attr_id.col, crosshair_color);
|
|
|
|
|
immVertex2f(attr_id.pos, 0, +f5);
|
|
|
|
|
immEnd();
|
|
|
|
|
|
|
|
|
|
immUnbindProgram();
|
|
|
|
|
|
|
|
|
|
GPU_blend(GPU_BLEND_NONE);
|
|
|
|
|
|
|
|
|
|
GPU_matrix_pop();
|
|
|
|
|
GPU_matrix_projection_set(original_proj);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Get offset in frame numbers of the reference frame relative to the current frame. */
|
|
|
|
|
static int get_reference_frame_offset(const Editing &editing, const RenderData &render_data)
|
|
|
|
|
{
|
|
|
|
|
if (editing.overlay_frame_flag & SEQ_EDIT_OVERLAY_FRAME_ABS) {
|
|
|
|
|
return editing.overlay_frame_abs - render_data.cfra;
|
|
|
|
|
}
|
|
|
|
|
return editing.overlay_frame_ofs;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Create GPUTexture from the given image buffer for drawing rendered sequencer frame on the
|
|
|
|
|
* color render frame buffer.
|
|
|
|
|
*
|
|
|
|
|
* The texture format and color space matches the CPU-side buffer.
|
|
|
|
|
*
|
|
|
|
|
* If both float and byte buffers are missing nullptr is returned.
|
|
|
|
|
* If channel configuration is incompatible with the texture nullptr is returned. */
|
|
|
|
|
static GPUTexture *create_texture(const ImBuf &ibuf)
|
|
|
|
|
{
|
|
|
|
|
const eGPUTextureUsage texture_usage = GPU_TEXTURE_USAGE_SHADER_READ |
|
|
|
|
|
GPU_TEXTURE_USAGE_ATTACHMENT;
|
|
|
|
|
|
|
|
|
|
GPUTexture *texture = nullptr;
|
|
|
|
|
|
|
|
|
|
if (ibuf.float_buffer.data) {
|
|
|
|
|
eGPUTextureFormat texture_format;
|
|
|
|
|
switch (ibuf.channels) {
|
|
|
|
|
case 1:
|
|
|
|
|
texture_format = GPU_R32F;
|
|
|
|
|
break;
|
|
|
|
|
case 3:
|
|
|
|
|
texture_format = GPU_RGB32F;
|
|
|
|
|
break;
|
|
|
|
|
case 4:
|
|
|
|
|
texture_format = GPU_RGBA32F;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
BLI_assert_msg(0, "Incompatible number of channels for float buffer in sequencer");
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
texture = GPU_texture_create_2d(
|
|
|
|
|
"seq_display_buf", ibuf.x, ibuf.y, 1, texture_format, texture_usage, nullptr);
|
|
|
|
|
GPU_texture_update(texture, GPU_DATA_FLOAT, ibuf.float_buffer.data);
|
|
|
|
|
}
|
|
|
|
|
else if (ibuf.byte_buffer.data) {
|
|
|
|
|
texture = GPU_texture_create_2d(
|
|
|
|
|
"seq_display_buf", ibuf.x, ibuf.y, 1, GPU_RGBA8, texture_usage, nullptr);
|
|
|
|
|
GPU_texture_update(texture, GPU_DATA_UBYTE, ibuf.byte_buffer.data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (texture) {
|
|
|
|
|
GPU_texture_filter_mode(texture, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return texture;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Get colorspace name of the image buffer used to create GPU texture.
|
|
|
|
|
*
|
|
|
|
|
* Needs to be kept in sync with create_texture() w.r.t which buffers are used to create the
|
|
|
|
|
* texture. If the image buffer does not specify color space explicitly scene linear is returned if
|
|
|
|
|
* there is a float buffer, and default byte space is returned if there is a byte buffer.
|
|
|
|
|
*
|
|
|
|
|
* If there are no buffers at all scene linear space is returned. */
|
|
|
|
|
static const char *get_texture_colorspace_name(const ImBuf &ibuf)
|
|
|
|
|
{
|
|
|
|
|
if (ibuf.float_buffer.data) {
|
|
|
|
|
if (ibuf.byte_buffer.colorspace) {
|
|
|
|
|
return IMB_colormanagement_colorspace_get_name(ibuf.float_buffer.colorspace);
|
|
|
|
|
}
|
|
|
|
|
return IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ibuf.byte_buffer.data) {
|
|
|
|
|
if (ibuf.byte_buffer.colorspace) {
|
|
|
|
|
return IMB_colormanagement_colorspace_get_name(ibuf.byte_buffer.colorspace);
|
|
|
|
|
}
|
|
|
|
|
return IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_DEFAULT_BYTE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Fail-safe fallback. */
|
|
|
|
|
return IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Part of the sequencer preview region drawing which renders images to the viewport's color render
|
|
|
|
|
* frame-buffer. */
|
|
|
|
|
static void sequencer_preview_draw_color_render(const SpaceSeq &space_sequencer,
|
|
|
|
|
const Editing &editing,
|
|
|
|
|
ARegion ®ion,
|
|
|
|
|
const ImBuf *current_ibuf,
|
|
|
|
|
GPUTexture *current_texture,
|
|
|
|
|
const ImBuf *reference_ibuf,
|
|
|
|
|
GPUTexture *reference_texture)
|
|
|
|
|
{
|
|
|
|
|
preview_draw_color_render_begin(region);
|
|
|
|
|
|
|
|
|
|
if (current_texture) {
|
|
|
|
|
BLI_assert(current_ibuf);
|
|
|
|
|
const rctf position = preview_get_full_position(region);
|
|
|
|
|
const rctf texture_coord = preview_get_full_texture_coord();
|
|
|
|
|
const char *texture_colorspace = get_texture_colorspace_name(*current_ibuf);
|
|
|
|
|
const bool predivide = (current_ibuf->float_buffer.data != nullptr);
|
|
|
|
|
preview_draw_texture_to_linear(
|
|
|
|
|
*current_texture, texture_colorspace, predivide, position, texture_coord);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (reference_texture) {
|
|
|
|
|
BLI_assert(reference_ibuf);
|
|
|
|
|
const rctf position = preview_get_reference_position(space_sequencer, editing, region);
|
|
|
|
|
const rctf texture_coord = preview_get_reference_texture_coord(space_sequencer, editing);
|
|
|
|
|
const char *texture_colorspace = get_texture_colorspace_name(*reference_ibuf);
|
|
|
|
|
const bool predivide = (reference_ibuf->float_buffer.data != nullptr);
|
|
|
|
|
preview_draw_texture_to_linear(
|
|
|
|
|
*reference_texture, texture_colorspace, predivide, position, texture_coord);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void draw_registered_callbacks(const bContext *C, ARegion ®ion)
|
|
|
|
|
{
|
|
|
|
|
GPUViewport *viewport = WM_draw_region_get_bound_viewport(®ion);
|
|
|
|
|
BLI_assert(viewport);
|
|
|
|
|
|
|
|
|
|
GPUFrameBuffer *overlay_fb = GPU_viewport_framebuffer_overlay_get(viewport);
|
|
|
|
|
|
|
|
|
|
GPU_framebuffer_bind(overlay_fb);
|
|
|
|
|
ED_region_draw_cb_draw(C, ®ion, REGION_DRAW_POST_VIEW);
|
|
|
|
|
GPU_framebuffer_bind_no_srgb(overlay_fb);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Part of the sequencer preview region drawing which renders information overlays to the
|
|
|
|
|
* viewport's overlay frame-buffer. */
|
|
|
|
|
static void sequencer_preview_draw_overlays(const bContext *C,
|
|
|
|
|
const wmWindowManager &wm,
|
|
|
|
|
const Scene *scene,
|
|
|
|
|
const SpaceSeq &space_sequencer,
|
|
|
|
|
const Editing &editing,
|
|
|
|
|
const ColorManagedViewSettings &view_settings,
|
|
|
|
|
const ColorManagedDisplaySettings &display_settings,
|
|
|
|
|
ARegion ®ion,
|
|
|
|
|
GPUTexture *current_texture,
|
|
|
|
|
GPUTexture *reference_texture,
|
|
|
|
|
const ImBuf *overlay_ibuf,
|
|
|
|
|
const int timeline_frame)
|
|
|
|
|
{
|
|
|
|
|
const bool is_playing = ED_screen_animation_playing(&wm);
|
|
|
|
|
const bool show_imbuf = check_show_imbuf(space_sequencer);
|
|
|
|
|
|
|
|
|
|
preview_draw_overlay_begin(region);
|
|
|
|
|
|
|
|
|
|
bool has_scopes = false;
|
|
|
|
|
if (overlay_ibuf &&
|
|
|
|
|
sequencer_calc_scopes(space_sequencer, view_settings, display_settings, *overlay_ibuf))
|
|
|
|
|
{
|
|
|
|
|
/* Draw scope. */
|
|
|
|
|
sequencer_draw_scopes(space_sequencer, region);
|
|
|
|
|
has_scopes = true;
|
|
|
|
|
}
|
|
|
|
|
else if (space_sequencer.flag & SEQ_USE_ALPHA) {
|
|
|
|
|
/* Draw checked-board. */
|
|
|
|
|
const View2D &v2d = region.v2d;
|
|
|
|
|
imm_draw_box_checker_2d(v2d.tot.xmin, v2d.tot.ymin, v2d.tot.xmax, v2d.tot.ymax);
|
|
|
|
|
|
|
|
|
|
/* Draw current and preview textures in a special way to pierce a hole in the overlay to make
|
|
|
|
|
* the actual image visible. */
|
|
|
|
|
GPU_blend(GPU_BLEND_OVERLAY_MASK_FROM_ALPHA);
|
|
|
|
|
if (current_texture) {
|
|
|
|
|
const rctf position = preview_get_full_position(region);
|
|
|
|
|
const rctf texture_coord = preview_get_full_texture_coord();
|
|
|
|
|
preview_draw_texture_simple(*current_texture, position, texture_coord);
|
|
|
|
|
}
|
|
|
|
|
if (reference_texture) {
|
|
|
|
|
const rctf position = preview_get_reference_position(space_sequencer, editing, region);
|
|
|
|
|
const rctf texture_coord = preview_get_reference_texture_coord(space_sequencer, editing);
|
|
|
|
|
preview_draw_texture_simple(*reference_texture, position, texture_coord);
|
|
|
|
|
}
|
|
|
|
|
GPU_blend(GPU_BLEND_NONE);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* The overlay framebuffer is fully cleared. Need to draw a full-frame transparent rectangle in
|
|
|
|
|
* it to make sequencer result visible. */
|
|
|
|
|
|
|
|
|
|
const rctf position = preview_get_full_position(region);
|
|
|
|
|
|
|
|
|
|
GPUVertFormat *imm_format = immVertexFormat();
|
|
|
|
|
const uint pos = GPU_vertformat_attr_add(imm_format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
|
|
|
|
|
|
|
|
|
GPU_blend(GPU_BLEND_OVERLAY_MASK_FROM_ALPHA);
|
|
|
|
|
|
|
|
|
|
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
|
|
|
|
|
immUniformColor3f(-.0f, 1.0f, 1.0f);
|
|
|
|
|
immRectf(pos, position.xmin, position.ymin, position.xmax, position.ymax);
|
|
|
|
|
immUnbindProgram();
|
|
|
|
|
|
|
|
|
|
GPU_blend(GPU_BLEND_NONE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Draw metadata. */
|
|
|
|
|
if (!has_scopes && overlay_ibuf) {
|
|
|
|
|
if ((space_sequencer.preview_overlay.flag & SEQ_PREVIEW_SHOW_METADATA) &&
|
|
|
|
|
(space_sequencer.flag & SEQ_SHOW_OVERLAY))
|
|
|
|
|
{
|
|
|
|
|
const View2D &v2d = region.v2d;
|
|
|
|
|
ED_region_image_metadata_draw(0.0, 0.0, overlay_ibuf, &v2d.tot, 1.0, 1.0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ibuf) {
|
|
|
|
|
bool has_scope = sequencer_calc_scopes(scene, sseq, ibuf);
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
if (show_imbuf && (space_sequencer.flag & SEQ_SHOW_OVERLAY)) {
|
|
|
|
|
sequencer_draw_borders_overlay(space_sequencer, region.v2d, scene);
|
|
|
|
|
|
|
|
|
|
/* 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);
|
|
|
|
|
/* Various overlays like stirp selection and text editing. */
|
|
|
|
|
preview_draw_all_image_overlays(C, scene, editing, timeline_frame);
|
|
|
|
|
|
|
|
|
|
if ((space_sequencer.preview_overlay.flag & SEQ_PREVIEW_SHOW_GPENCIL) && space_sequencer.gpd) {
|
|
|
|
|
sequencer_draw_gpencil_overlay(C);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (show_imbuf && (sseq->flag & SEQ_SHOW_OVERLAY)) {
|
|
|
|
|
sequencer_draw_borders_overlay(sseq, v2d, scene);
|
|
|
|
|
draw_registered_callbacks(C, region);
|
|
|
|
|
|
|
|
|
|
UI_view2d_view_restore(C);
|
|
|
|
|
|
|
|
|
|
/* No need to show the cursor for scopes. */
|
|
|
|
|
if ((is_playing == false) && (space_sequencer.mainb == SEQ_DRAW_IMG_IMBUF) &&
|
|
|
|
|
is_cursor_visible(space_sequencer))
|
|
|
|
|
{
|
|
|
|
|
GPU_color_mask(true, true, true, true);
|
|
|
|
|
GPU_depth_mask(false);
|
|
|
|
|
GPU_depth_test(GPU_DEPTH_NONE);
|
|
|
|
|
|
|
|
|
|
const float2 cursor_pixel = seq::image_preview_unit_to_px(scene, space_sequencer.cursor);
|
|
|
|
|
draw_cursor_2d(®ion, cursor_pixel);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (scene->ed != nullptr) {
|
|
|
|
|
Editing *ed = seq::editing_get(scene);
|
|
|
|
|
ListBase *channels = seq::channels_displayed_get(ed);
|
|
|
|
|
blender::VectorSet strips = seq::query_rendered_strips(
|
|
|
|
|
scene, channels, ed->seqbasep, timeline_frame, 0);
|
|
|
|
|
Strip *active_seq = seq::select_active_get(scene);
|
|
|
|
|
for (Strip *strip : strips) {
|
|
|
|
|
strip_draw_image_origin_and_outline(C, strip, strip == active_seq);
|
|
|
|
|
text_edit_draw(C);
|
|
|
|
|
/* Gizmos. */
|
|
|
|
|
if ((is_playing == false) && (space_sequencer.gizmo_flag & SEQ_GIZMO_HIDE) == 0) {
|
|
|
|
|
WM_gizmomap_draw(region.runtime->gizmo_map, C, WM_GIZMOMAP_DRAWSTEP_2D);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* FPS counter. */
|
|
|
|
|
if ((U.uiflag & USER_SHOW_FPS) && ED_screen_animation_no_scrub(&wm)) {
|
|
|
|
|
const rcti *rect = ED_region_visible_rect(®ion);
|
|
|
|
|
int xoffset = rect->xmin + U.widget_unit;
|
|
|
|
|
int yoffset = rect->ymax;
|
|
|
|
|
|
|
|
|
|
/* #ED_scene_draw_fps does not set text/shadow colors, except when frame-rate is too low, then
|
|
|
|
|
* it sets text color to red. Make sure the "normal case" also has legible colors. */
|
|
|
|
|
const int font_id = BLF_default();
|
|
|
|
|
float text_color[4] = {1, 1, 1, 1}, shadow_color[4] = {0, 0, 0, 0.8f};
|
|
|
|
|
BLF_color4fv(font_id, text_color);
|
|
|
|
|
BLF_enable(font_id, BLF_SHADOW);
|
|
|
|
|
BLF_shadow_offset(font_id, 0, 0);
|
|
|
|
|
BLF_shadow(font_id, FontShadowType::Outline, shadow_color);
|
|
|
|
|
|
|
|
|
|
ED_scene_draw_fps(scene, xoffset, &yoffset);
|
|
|
|
|
|
|
|
|
|
BLF_disable(font_id, BLF_SHADOW);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void sequencer_preview_region_draw(const bContext *C, ARegion *region)
|
|
|
|
|
{
|
|
|
|
|
const char *view_names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
|
|
|
|
|
|
|
|
|
|
const ScrArea *area = CTX_wm_area(C);
|
|
|
|
|
const SpaceSeq &space_sequencer = *static_cast<const SpaceSeq *>(area->spacedata.first);
|
|
|
|
|
const Scene *scene = CTX_data_scene(C);
|
|
|
|
|
|
|
|
|
|
if (!scene->ed || space_sequencer.render_size == SEQ_RENDER_SIZE_NONE) {
|
|
|
|
|
sequencer_preview_draw_empty(*region);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const Editing &editing = *scene->ed;
|
|
|
|
|
const RenderData &render_data = scene->r;
|
|
|
|
|
|
|
|
|
|
if (!preview_draw_begin(C, render_data, scene->view_settings, scene->display_settings, *region))
|
|
|
|
|
{
|
|
|
|
|
sequencer_preview_draw_empty(*region);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const bool show_imbuf = check_show_imbuf(space_sequencer);
|
|
|
|
|
|
|
|
|
|
const bool draw_overlay = (space_sequencer.flag & SEQ_SHOW_OVERLAY);
|
|
|
|
|
const bool draw_frame_overlay = (editing.overlay_frame_flag & SEQ_EDIT_OVERLAY_FRAME_SHOW) &&
|
|
|
|
|
draw_overlay;
|
|
|
|
|
const bool need_current_frame = !(draw_frame_overlay && (space_sequencer.overlay_frame_type ==
|
|
|
|
|
SEQ_OVERLAY_FRAME_TYPE_REFERENCE));
|
|
|
|
|
const bool need_reference_frame = draw_frame_overlay && space_sequencer.overlay_frame_type !=
|
|
|
|
|
SEQ_OVERLAY_FRAME_TYPE_CURRENT;
|
|
|
|
|
|
|
|
|
|
int timeline_frame = render_data.cfra;
|
|
|
|
|
if (sequencer_draw_get_transform_preview(space_sequencer, *scene)) {
|
|
|
|
|
timeline_frame = sequencer_draw_get_transform_preview_frame(scene);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* GPU textures for the current and reference frames.
|
|
|
|
|
*
|
|
|
|
|
* When non-nullptr they are to be drawn (in other words, when they are non-nullptr the
|
|
|
|
|
* corresponding draw_current_frame and draw_reference_frame is true). */
|
|
|
|
|
GPUTexture *current_texture = nullptr;
|
|
|
|
|
GPUTexture *reference_texture = nullptr;
|
|
|
|
|
|
|
|
|
|
/* Get image buffers before setting up GPU state for drawing. This is because
|
|
|
|
|
* sequencer_ibuf_get() might not properly restore the state.
|
|
|
|
|
* Additionally, some image buffers might be needed for both color render and overlay drawing. */
|
|
|
|
|
ImBuf *current_ibuf = nullptr;
|
|
|
|
|
ImBuf *reference_ibuf = nullptr;
|
|
|
|
|
if (need_current_frame) {
|
|
|
|
|
current_ibuf = sequencer_ibuf_get(
|
|
|
|
|
C, timeline_frame, view_names[space_sequencer.multiview_eye]);
|
|
|
|
|
if (show_imbuf && current_ibuf) {
|
|
|
|
|
current_texture = create_texture(*current_ibuf);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (need_reference_frame) {
|
|
|
|
|
const int offset = get_reference_frame_offset(editing, render_data);
|
|
|
|
|
reference_ibuf = sequencer_ibuf_get(
|
|
|
|
|
C, timeline_frame + offset, view_names[space_sequencer.multiview_eye]);
|
|
|
|
|
if (show_imbuf && reference_ibuf) {
|
|
|
|
|
reference_texture = create_texture(*reference_ibuf);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (draw_gpencil && show_imbuf && (sseq->flag & SEQ_SHOW_OVERLAY)) {
|
|
|
|
|
sequencer_draw_gpencil_overlay(C);
|
|
|
|
|
}
|
|
|
|
|
/* Image buffer used for overlays: scopes, metadata etc. */
|
|
|
|
|
ImBuf *overlay_ibuf = need_current_frame ? current_ibuf : reference_ibuf;
|
|
|
|
|
|
|
|
|
|
/* Draw parts of the preview region to the corresponding frame buffers. */
|
|
|
|
|
sequencer_preview_draw_color_render(space_sequencer,
|
|
|
|
|
editing,
|
|
|
|
|
*region,
|
|
|
|
|
current_ibuf,
|
|
|
|
|
current_texture,
|
|
|
|
|
reference_ibuf,
|
|
|
|
|
reference_texture);
|
|
|
|
|
sequencer_preview_draw_overlays(C,
|
|
|
|
|
*CTX_wm_manager(C),
|
|
|
|
|
scene,
|
|
|
|
|
space_sequencer,
|
|
|
|
|
editing,
|
|
|
|
|
scene->view_settings,
|
|
|
|
|
scene->display_settings,
|
|
|
|
|
*region,
|
|
|
|
|
current_texture,
|
|
|
|
|
reference_texture,
|
|
|
|
|
overlay_ibuf,
|
|
|
|
|
timeline_frame);
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
sequencer_draw_maskedit(C, scene, region, sseq);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* Draw registered callbacks. */
|
|
|
|
|
GPU_framebuffer_bind(framebuffer_overlay);
|
|
|
|
|
ED_region_draw_cb_draw(C, region, REGION_DRAW_POST_VIEW);
|
|
|
|
|
GPU_framebuffer_bind_no_srgb(framebuffer_overlay);
|
|
|
|
|
|
|
|
|
|
if (ibuf) {
|
|
|
|
|
IMB_freeImBuf(ibuf);
|
|
|
|
|
/* Free textures. */
|
|
|
|
|
if (current_texture) {
|
|
|
|
|
GPU_texture_free(current_texture);
|
|
|
|
|
}
|
|
|
|
|
if (reference_texture) {
|
|
|
|
|
GPU_texture_free(reference_texture);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UI_view2d_view_restore(C);
|
|
|
|
|
seq_prefetch_wm_notify(C, scene);
|
|
|
|
|
/* Free CPU side resources. */
|
|
|
|
|
IMB_freeImBuf(current_ibuf);
|
|
|
|
|
IMB_freeImBuf(reference_ibuf);
|
|
|
|
|
|
|
|
|
|
preview_draw_end(C);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace blender::ed::vse
|
|
|
|
|
|