1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
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
|