diff options
Diffstat (limited to 'src/ui/widget/optglarea.cpp')
-rw-r--r-- | src/ui/widget/optglarea.cpp | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/src/ui/widget/optglarea.cpp b/src/ui/widget/optglarea.cpp new file mode 100644 index 0000000..72ec362 --- /dev/null +++ b/src/ui/widget/optglarea.cpp @@ -0,0 +1,127 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +#include <cassert> +#include "optglarea.h" + +namespace Inkscape { +namespace UI { +namespace Widget { + +OptGLArea::OptGLArea() +{ + set_app_paintable(true); // No problem for GTK4 port since this whole widget will be deleted. + opengl_enabled = false; +} + +void OptGLArea::on_realize() +{ + Gtk::DrawingArea::on_realize(); + if (opengl_enabled) init_opengl(); +} + +void OptGLArea::on_unrealize() +{ + if (context) { + if (framebuffer) { + context->make_current(); + delete_framebuffer(); + } + if (context == Gdk::GLContext::get_current()) { + Gdk::GLContext::clear_current(); // ? + } + context.reset(); + } + Gtk::DrawingArea::on_unrealize(); +} + +void OptGLArea::on_size_allocate(Gtk::Allocation &allocation) +{ + Gtk::DrawingArea::on_size_allocate(allocation); + if (get_realized()) need_resize = true; +} + +void OptGLArea::set_opengl_enabled(bool enabled) +{ + if (opengl_enabled == enabled) return; + opengl_enabled = enabled; + if (opengl_enabled && get_realized()) init_opengl(); +} + +void OptGLArea::init_opengl() +{ + context = create_context(); + if (!context) opengl_enabled = false; + framebuffer = 0; + need_resize = true; +} + +void OptGLArea::make_current() +{ + assert(context); + context->make_current(); +} + +bool OptGLArea::on_draw(const Cairo::RefPtr<Cairo::Context> &cr) +{ + if (opengl_enabled) { + context->make_current(); + + if (!framebuffer) { + create_framebuffer(); + } + + if (need_resize) { + resize_framebuffer(); + need_resize = false; + } + + paint_widget(cr); + + int s = get_scale_factor(); + int w = get_allocated_width() * s; + int h = get_allocated_height() * s; + gdk_cairo_draw_from_gl(cr->cobj(), get_window()->gobj(), renderbuffer, GL_RENDERBUFFER, s, 0, 0, w, h); + + context->make_current(); // ? + } else { + paint_widget(cr); + } + + return true; +} + +void OptGLArea::bind_framebuffer() const +{ + assert(context); + glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, stencilbuffer); +} + +void OptGLArea::create_framebuffer() +{ + glGenFramebuffers (1, &framebuffer); + glGenRenderbuffers(1, &renderbuffer); + glGenRenderbuffers(1, &stencilbuffer); +} + +void OptGLArea::delete_framebuffer() +{ + glDeleteRenderbuffers(1, &renderbuffer); + glDeleteRenderbuffers(1, &stencilbuffer); + glDeleteFramebuffers (1, &framebuffer); +} + +void OptGLArea::resize_framebuffer() const +{ + int s = get_scale_factor(); + int w = get_allocated_width() * s; + int h = get_allocated_height() * s; + glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer); + glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB8, w, h); + glBindRenderbuffer(GL_RENDERBUFFER, stencilbuffer); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, w, h); +} + +} // namespace Widget +} // namespace UI +} // namespace Inkscape |