Route paint render state through GL backend

This commit is contained in:
2026-06-04 22:19:54 +02:00
parent 24197c5f7e
commit d55f26d637
7 changed files with 304 additions and 73 deletions

View File

@@ -198,6 +198,74 @@ void unbind_texture_2d()
LOG("Canvas texture unbind dispatch failed because: %s", status.message);
}
void enable_opengl_state(std::uint32_t state) noexcept
{
glEnable(static_cast<GLenum>(state));
}
void disable_opengl_state(std::uint32_t state) noexcept
{
glDisable(static_cast<GLenum>(state));
}
void set_opengl_viewport(std::int32_t x, std::int32_t y, std::int32_t width, std::int32_t height) noexcept
{
glViewport(static_cast<GLint>(x), static_cast<GLint>(y), static_cast<GLsizei>(width), static_cast<GLsizei>(height));
}
void set_opengl_scissor(std::int32_t x, std::int32_t y, std::int32_t width, std::int32_t height) noexcept
{
glScissor(static_cast<GLint>(x), static_cast<GLint>(y), static_cast<GLsizei>(width), static_cast<GLsizei>(height));
}
void apply_canvas_viewport(std::int32_t x, std::int32_t y, std::int32_t width, std::int32_t height)
{
const auto status = pp::renderer::gl::apply_opengl_viewport(
pp::renderer::gl::OpenGlViewportRect {
.x = x,
.y = y,
.width = width,
.height = height,
},
pp::renderer::gl::OpenGlViewportDispatch {
.viewport = set_opengl_viewport,
});
if (!status.ok())
LOG("Canvas viewport dispatch failed because: %s", status.message);
}
void apply_canvas_scissor(std::int32_t x, std::int32_t y, std::int32_t width, std::int32_t height)
{
const auto status = pp::renderer::gl::apply_opengl_scissor_rect(
pp::renderer::gl::OpenGlScissorRect {
.enabled = 1U,
.x = x,
.y = y,
.width = width,
.height = height,
},
pp::renderer::gl::OpenGlScissorDispatch {
.enable = enable_opengl_state,
.disable = disable_opengl_state,
.scissor = set_opengl_scissor,
});
if (!status.ok())
LOG("Canvas scissor dispatch failed because: %s", status.message);
}
void apply_canvas_capability(std::uint32_t state, bool enabled)
{
const auto status = pp::renderer::gl::apply_opengl_capability(
state,
enabled,
pp::renderer::gl::OpenGlCapabilityDispatch {
.enable = enable_opengl_state,
.disable = disable_opengl_state,
});
if (!status.ok())
LOG("Canvas capability dispatch failed because: %s", status.message);
}
void gen_opengl_renderbuffers(std::uint32_t count, std::uint32_t* ids) noexcept
{
glGenRenderbuffers(static_cast<GLsizei>(count), reinterpret_cast<GLuint*>(ids));
@@ -427,12 +495,12 @@ void Canvas::stroke_draw_mix(const glm::vec2& bb_min, const glm::vec2& bb_sz)
m_mixer.bindFramebuffer();
glViewport(0, 0, m_mixer.getWidth(), m_mixer.getHeight());
glDisable(depth_test_state());
glEnable(scissor_test_state());
glDisable(blend_state());
apply_canvas_viewport(0, 0, m_mixer.getWidth(), m_mixer.getHeight());
apply_canvas_capability(depth_test_state(), false);
apply_canvas_capability(scissor_test_state(), true);
apply_canvas_capability(blend_state(), false);
glScissor(bb_min.x, bb_min.y, bb_sz.x, bb_sz.y);
apply_canvas_scissor(bb_min.x, bb_min.y, bb_sz.x, bb_sz.y);
auto layer_index = m_current_layer_idx;
for (int plane_index = 0; plane_index < 6; plane_index++)
@@ -718,7 +786,7 @@ void Canvas::stroke_draw()
const auto& dual_brush = m_dual_stroke->m_brush;
auto ortho_proj = glm::ortho(0.f, (float)m_width, 0.f, (float)m_height, -1.f, 1.f);
glViewport(0, 0, m_width, m_height);
apply_canvas_viewport(0, 0, m_width, m_height);
m_sampler_brush.bind(0);
m_sampler_nearest.bind(1);
@@ -733,7 +801,7 @@ void Canvas::stroke_draw()
const auto stroke_feedback = canvas_destination_feedback_plan(m_width, m_height);
const bool copy_stroke_destination = !stroke_feedback.reads_destination_color;
glDisable(blend_state());
apply_canvas_capability(blend_state(), false);
ShaderManager::use(kShader::Stroke);
ShaderManager::u_int(kShaderUniform::Tex, 0); // brush
if (copy_stroke_destination)
@@ -907,7 +975,7 @@ void Canvas::stroke_draw()
m_sampler_nearest.unbind();
m_sampler_stencil.unbind();
glViewport(vp[0], vp[1], vp[2], vp[3]);
apply_canvas_viewport(vp[0], vp[1], vp[2], vp[3]);
glClearColor(cc[0], cc[1], cc[2], cc[3]);
if (m_commit_delayed)
@@ -1032,8 +1100,8 @@ void Canvas::stroke_commit()
App::I->title_update();
// prepare common states
glViewport(0, 0, m_width, m_height);
glDisable(blend_state());
apply_canvas_viewport(0, 0, m_width, m_height);
apply_canvas_capability(blend_state(), false);
const auto& b = m_current_stroke->m_brush;
@@ -1190,8 +1258,8 @@ void Canvas::stroke_commit()
}
// restore viewport and clear color states
blend ? glEnable(blend_state()) : glDisable(blend_state());
glViewport(vp[0], vp[1], vp[2], vp[3]);
blend ? apply_canvas_capability(blend_state(), true) : apply_canvas_capability(blend_state(), false);
apply_canvas_viewport(vp[0], vp[1], vp[2], vp[3]);
glClearColor(cc[0], cc[1], cc[2], cc[3]);
set_active_texture_unit(0);
@@ -1226,7 +1294,7 @@ void Canvas::draw_merge(bool draw_checkerboard, std::array<bool, 6> faces /*= SI
{
assert(App::I->is_render_thread());
glViewport(0, 0, m_width, m_height);
apply_canvas_viewport(0, 0, m_width, m_height);
auto ortho = glm::ortho<float>(-0.5f, 0.5f, -0.5f, 0.5f, -1.f, 1.f);
const auto& b = m_current_stroke->m_brush;
@@ -1239,7 +1307,7 @@ void Canvas::draw_merge(bool draw_checkerboard, std::array<bool, 6> faces /*= SI
const bool copy_blend_destination = use_blend && !blend_gate.reads_destination_color;
// if not using shader blend, use gl rasterizer blend
glDisable(depth_test_state());
apply_canvas_capability(depth_test_state(), false);
for (int plane_index = 0; plane_index < 6; plane_index++)
{
@@ -1251,7 +1319,7 @@ void Canvas::draw_merge(bool draw_checkerboard, std::array<bool, 6> faces /*= SI
if (use_blend)
{
glDisable(blend_state());
apply_canvas_capability(blend_state(), false);
m_layers_merge.rtt(plane_index).clear();
}
else
@@ -1263,7 +1331,7 @@ void Canvas::draw_merge(bool draw_checkerboard, std::array<bool, 6> faces /*= SI
ShaderManager::u_mat4(kShaderUniform::MVP, ortho);
m_plane.draw_fill();
}
glEnable(blend_state());
apply_canvas_capability(blend_state(), true);
}
for (int layer_index = 0; layer_index < m_layers.size(); layer_index++)
@@ -1434,7 +1502,7 @@ void Canvas::draw_merge(bool draw_checkerboard, std::array<bool, 6> faces /*= SI
// draw the grid behind the layers using a temporary copy
if (use_blend)
{
glEnable(blend_state());
apply_canvas_capability(blend_state(), true);
//draw the grid
if (draw_checkerboard)
@@ -1595,8 +1663,8 @@ void Canvas::layer_merge(int source_idx, int dest_idx) // m_layer index
App::I->render_task([&]
{
// prepare common states
glViewport(0, 0, m_width, m_height);
glDisable(blend_state());
apply_canvas_viewport(0, 0, m_width, m_height);
apply_canvas_capability(blend_state(), false);
for (int i = 0; i < 6; i++)
{
@@ -2017,7 +2085,7 @@ void Canvas::import_equirectangular_thread(std::string file_path, std::shared_pt
Plane plane;
plane.create<1>(2, 2);
draw_objects([&](const glm::mat4& camera, const glm::mat4& proj, int i) {
glDisable(depth_test_state());
apply_canvas_capability(depth_test_state(), false);
tex.update(img.m_data.get() + indices[i] * stride);
m_sampler.bind(0);
set_active_texture_unit(0);
@@ -2038,7 +2106,7 @@ void Canvas::import_equirectangular_thread(std::string file_path, std::shared_pt
Sphere sphere;
sphere.create<64, 64>(2.f);
draw_objects([&](const glm::mat4& camera, const glm::mat4& proj, int i) {
glDisable(depth_test_state());
apply_canvas_capability(depth_test_state(), false);
m_sampler.bind(0);
set_active_texture_unit(0);
tex.bind();
@@ -2174,9 +2242,9 @@ void Canvas::export_depth_thread(std::string file_name)
rtt.bindFramebuffer();
rtt.clear({ 0, 0, 0, 1 });
glEnable(blend_state());
glDisable(depth_test_state());
glViewport(0, 0, rtt.getWidth(), rtt.getHeight());
apply_canvas_capability(blend_state(), true);
apply_canvas_capability(depth_test_state(), false);
apply_canvas_viewport(0, 0, rtt.getWidth(), rtt.getHeight());
for (int plane_index = 0; plane_index < 6; plane_index++)
{
auto plane_mvp_z = proj * camera *
@@ -2209,9 +2277,9 @@ void Canvas::export_depth_thread(std::string file_name)
{
rtt.bindFramebuffer();
rtt.clear({ 0, 0, 0, 1 });
glEnable(blend_state());
glDisable(depth_test_state());
glViewport(0, 0, rtt.getWidth(), rtt.getHeight());
apply_canvas_capability(blend_state(), true);
apply_canvas_capability(depth_test_state(), false);
apply_canvas_viewport(0, 0, rtt.getWidth(), rtt.getHeight());
for (int layer_index = 0; layer_index < m_layers.size(); layer_index++)
{
for (int plane_index = 0; plane_index < 6; plane_index++)
@@ -2901,7 +2969,7 @@ Image Canvas::thumbnail_generate(int w, int h)
auto blend = glIsEnabled(blend_state());
// prepare common states
glViewport(0, 0, w, h);
apply_canvas_viewport(0, 0, w, h);
RTT fb;
fb.create(w, h);
@@ -2919,7 +2987,7 @@ Image Canvas::thumbnail_generate(int w, int h)
fb.clear({ 1, 1, 1, 0 });
for (int i = 0; i < 6; i++)
{
glDisable(blend_state());
apply_canvas_capability(blend_state(), false);
auto plane_mvp = proj * m_mv * m_plane_transform[i] * glm::translate(glm::vec3(0, 0, -1));
ShaderManager::use(kShader::TextureBlend);
@@ -2969,7 +3037,7 @@ Image Canvas::thumbnail_generate(int w, int h)
m_face_plane.draw_fill();
// now blend with the background
glEnable(blend_state());
apply_canvas_capability(blend_state(), true);
ShaderManager::use(kShader::Texture);
ShaderManager::u_int(kShaderUniform::Tex, 0);
ShaderManager::u_mat4(kShaderUniform::MVP, glm::ortho(-.5f, .5f, -.5f, .5f, -1.f, 1.f));
@@ -2988,8 +3056,8 @@ Image Canvas::thumbnail_generate(int w, int h)
blendtex.destroy();
// restore viewport and clear color states
blend ? glEnable(blend_state()) : glDisable(blend_state());
glViewport(vp[0], vp[1], vp[2], vp[3]);
blend ? apply_canvas_capability(blend_state(), true) : apply_canvas_capability(blend_state(), false);
apply_canvas_viewport(vp[0], vp[1], vp[2], vp[3]);
glClearColor(cc[0], cc[1], cc[2], cc[3]);
set_active_texture_unit(0);
});
@@ -3036,8 +3104,8 @@ void Canvas::draw_objects_direct(std::function<void(const glm::mat4& camera, con
auto blend = glIsEnabled(blend_state());
// prepare common states
glViewport(0, 0, layer.w, layer.h);
glDisable(blend_state());
apply_canvas_viewport(0, 0, layer.w, layer.h);
apply_canvas_capability(blend_state(), false);
GLuint rboID = allocate_canvas_depth_renderbuffer(layer.w, layer.h);
@@ -3060,8 +3128,8 @@ void Canvas::draw_objects_direct(std::function<void(const glm::mat4& camera, con
delete_canvas_renderbuffer(rboID);
// restore viewport and clear color states
blend ? glEnable(blend_state()) : glDisable(blend_state());
glViewport(vp[0], vp[1], vp[2], vp[3]);
blend ? apply_canvas_capability(blend_state(), true) : apply_canvas_capability(blend_state(), false);
apply_canvas_viewport(vp[0], vp[1], vp[2], vp[3]);
glClearColor(cc[0], cc[1], cc[2], cc[3]);
set_active_texture_unit(0);
});
@@ -3079,8 +3147,8 @@ void Canvas::draw_objects(std::function<void(const glm::mat4& camera, const glm:
auto blend = glIsEnabled(blend_state());
// prepare common states
glViewport(0, 0, layer.w, layer.h);
glDisable(blend_state());
apply_canvas_viewport(0, 0, layer.w, layer.h);
apply_canvas_capability(blend_state(), false);
GLuint rboID = allocate_canvas_depth_renderbuffer(layer.w, layer.h);
@@ -3166,8 +3234,8 @@ void Canvas::draw_objects(std::function<void(const glm::mat4& camera, const glm:
rtt.destroy();
// restore viewport and clear color states
blend ? glEnable(blend_state()) : glDisable(blend_state());
glViewport(vp[0], vp[1], vp[2], vp[3]);
blend ? apply_canvas_capability(blend_state(), true) : apply_canvas_capability(blend_state(), false);
apply_canvas_viewport(vp[0], vp[1], vp[2], vp[3]);
glClearColor(cc[0], cc[1], cc[2], cc[3]);
set_active_texture_unit(0);
});