// SPDX-License-Identifier: GPL-2.0-or-later #include #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 &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