summaryrefslogtreecommitdiffstats
path: root/src/ui/widget/optglarea.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui/widget/optglarea.cpp')
-rw-r--r--src/ui/widget/optglarea.cpp127
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