-
Notifications
You must be signed in to change notification settings - Fork 22
/
Copy pathscreen.cpp
145 lines (121 loc) · 3.97 KB
/
screen.cpp
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#include "screen.hpp"
#include "debug.hpp"
Screen::Screen(const Evdi& evdi, std::vector<unsigned char>& edid, bool separateCursorEvents)
: evdi(evdi)
, buffersRegistered(false)
, bufferToUpdate(0)
{
rects.resize(16); // FIXME: remove magic const
if (edid.size() > 0) {
evdi.connect(edid.data(), edid.size());
} else {
evdi.connect(nullptr, 0);
}
context.dpms_handler = dpms_handler;
context.mode_changed_handler = mode_change_handler;
context.update_ready_handler = update_ready_handler;
context.crtc_state_handler = crtc_state_handler;
context.cursor_set_handler = cursor_set_handler;
context.cursor_move_handler = cursor_move_handler;
context.user_data = this;
if (separateCursorEvents) {
enable_cursor_events();
}
}
Screen::~Screen()
{
evdi.disconnect();
}
int Screen::event_source() const
{
return evdi.get_event_source();
}
void Screen::handle_events()
{
evdi.handle_events(&context);
}
void Screen::enable_cursor_events() const
{
evdi.enable_cursor_events();
}
void Screen::mode_change_handler(evdi_mode mode, void* user_data)
{
static_cast<Screen*>(user_data)->on_mode_change(mode);
}
void Screen::dpms_handler(int dpms_mode, void* user_data)
{
static_cast<Screen*>(user_data)->on_dpms_notification(dpms_mode);
}
void Screen::update_ready_handler(int buffer_to_be_updated, void* user_data)
{
static_cast<Screen*>(user_data)->on_update_ready(buffer_to_be_updated);
}
void Screen::crtc_state_handler(int state, void* user_data)
{
static_cast<Screen*>(user_data)->on_crtc_state_change(state);
}
void Screen::cursor_set_handler(evdi_cursor_set cursor_set, void* user_data)
{
static_cast<Screen*>(user_data)->on_cursor_set(cursor_set);
}
void Screen::cursor_move_handler(evdi_cursor_move cursor_move, void* user_data)
{
static_cast<Screen*>(user_data)->on_cursor_move(cursor_move);
}
void Screen::on_mode_change(evdi_mode mode)
{
logging << "Mode change: " << mode.width << "x" << mode.height << "@" << mode.refresh_rate << "Hz "
<< mode.bits_per_pixel << "bpp fmt:" << mode.pixel_format << std::endl;
buffersRegistered = false;
for (const auto& [buffer_id, buffer] : buffers) {
evdi.unregister_buffer(buffer_id);
}
buffers.clear();
for (int i = 0; i < BUFFER_COUNT; ++i) {
buffers[i] = std::make_unique<Buffer>(i, mode.width, mode.height, mode.bits_per_pixel / 8 * mode.width);
evdi.register_buffer(buffers[i]->get());
}
buffersRegistered = true;
}
int Screen::on_update_ready(int buffer_to_be_updated)
{
//logging << "Update ready for buffer " << buffer_to_be_updated << std::endl;
int num_rects;
evdi.grab_pixels(rects.data(), &num_rects);
if (num_rects > 1) {
// Do not bother logging single dirty rects, only log more interesting cases
logging << "Have " << num_rects << " to redraw" << std::endl;
for (size_t i = 0; i < num_rects; ++i) {
logging << "[" << rects[i].x1 << "," << rects[i].y1 << ":" << rects[i].x2 << "," << rects[i].y2 << "] ";
}
logging << std::endl;
}
return num_rects;
}
void Screen::on_dpms_notification(int dpms_mode)
{
logging << "DPMS event: " << dpms_mode << std::endl;
}
void Screen::on_crtc_state_change(int state)
{
logging << "CRTC state change: " << state << std::endl;
}
void Screen::on_cursor_set(evdi_cursor_set cursor_set)
{
logging << "Cursor " << (cursor_set.enabled ? "ON" : "OFF") << ": Hot[X,Y]=" << cursor_set.hot_x << "," << cursor_set.hot_y << std::endl;
}
void Screen::on_cursor_move(evdi_cursor_move cursor_move)
{
logging << "Cursor moved to " << cursor_move.x << "," << cursor_move.y << std::endl;
}
void Screen::update()
{
if (!buffersRegistered) {
return;
}
//logging << "Asking to update buffer " << bufferToUpdate << std::endl;
if (evdi.request_update(bufferToUpdate)) {
on_update_ready(bufferToUpdate);
}
bufferToUpdate = (bufferToUpdate + 1) % BUFFER_COUNT;
}