Add a `.data<T>()` method that retrieves a mutable span. This is useful more and more as we change to filling in vertex buffer data arrays directly, and compared to raw pointers it's safer too because of asserts in debug builds. Pull Request: https://projects.blender.org/blender/blender/pulls/123338
172 lines
4.7 KiB
C++
172 lines
4.7 KiB
C++
/* 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.hh"
|
|
#include "GPU_index_buffer.hh"
|
|
#include "GPU_vertex_buffer.hh"
|
|
|
|
struct ColorVertex {
|
|
blender::float2 pos;
|
|
blender::ColorTheme4b color;
|
|
};
|
|
static_assert(sizeof(ColorVertex) == 12);
|
|
|
|
static blender::gpu::IndexBuf *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_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_SMOOTH_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 color1[4],
|
|
const uchar color2[4],
|
|
const uchar color3[4],
|
|
const uchar color4[4])
|
|
{
|
|
if (quads_num >= MAX_QUADS) {
|
|
draw();
|
|
}
|
|
if (quads_num == 0) {
|
|
verts_quads = vbo_quads->data<ColorVertex>().data();
|
|
BLI_assert(verts_quads != nullptr);
|
|
}
|
|
|
|
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;
|
|
*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 = vbo_lines->data<ColorVertex>().data();
|
|
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 color1[4], const uchar color2[4])
|
|
{
|
|
if (lines_num + 1 > MAX_LINES) {
|
|
draw();
|
|
}
|
|
if (lines_num == 0) {
|
|
verts_lines = vbo_lines->data<ColorVertex>().data();
|
|
BLI_assert(verts_lines != nullptr);
|
|
}
|
|
|
|
ColorVertex v0 = {blender::float2(x1, y1), color1};
|
|
ColorVertex v1 = {blender::float2(x2, y2), color2};
|
|
|
|
*verts_lines++ = v0;
|
|
*verts_lines++ = v1;
|
|
|
|
lines_num++;
|
|
}
|