can not get the correct partial update( damage area) when kwin_x11 enable effects composite
I need to use damage area to mark the part of the image updated in vnc-x11 to reduce the image data transmitted by the network(why do i need it?it is as important as using pipewire to report damage area in kwin_wayland).
if disable effects composite damage area is correct: --------- damage event ---------- rea: x: 71, y: 78, w: 413, h: 337 --------- damage event ---------- area: x: 71, y: 415, w: 413, h: 551 --------- damage event ---------- area: x: 949, y: 415, w: 661, h: 551
but enable effects composite, damage area will always be the size of my monitor: --------- damage event ---------- rea: x: 0, y: 0, w: 2560, h: 1440 --------- damage event ---------- area: x: 0, y: 0, w: 2560, h: 1440 --------- damage event ---------- area: x: 0, y: 0, w: 2560, h: 1440
Here is my test code(of course, you can also choose not to use this code, and open the damage report in xorg-server, but in this case /var/log/Xorg.0.log will generate a lot of logs):
#include <cstring>
#include <iostream>
#include <memory>
#include <sys/select.h>
#include <xcb/xcb.h>
#include <xcb/xcb_event.h>
#include <xcb/damage.h>
using namespace std;
struct xcb_connection_deleter
{
void operator()(xcb_connection_t* c)
{
if (c)
{
xcb_disconnect(c);
}
}
};
xcb_screen_t* screen_of_display(xcb_connection_t* c, int screen)
{
for (auto iter = xcb_setup_roots_iterator(xcb_get_setup(c)); iter.rem; --screen, xcb_screen_next(&iter))
{
if (screen == 0)
{
return iter.data;
}
}
return nullptr;
}
int main()
{
unique_ptr<xcb_connection_t, xcb_connection_deleter> connection{xcb_connect(nullptr, nullptr)};
int rc = xcb_connection_has_error(connection.get());
if (rc != 0)
{
cout << "xcb connection error: " << rc << endl;
exit(1);
}
const auto extreply = xcb_get_extension_data(connection.get(), &xcb_damage_id);
if (!extreply->present)
{
cout << "xcb-damage is not present\n";
exit(1);
}
uint8_t damageEvent = extreply->first_event;
auto cookie = xcb_damage_query_version(connection.get(), XCB_DAMAGE_MAJOR_VERSION, XCB_DAMAGE_MINOR_VERSION);
xcb_generic_error_t* e = 0;
auto reply = xcb_damage_query_version_reply(connection.get(), cookie, &e);
if (!reply)
{
cout << "xcb_damage_use_extension error: " << e->error_code << endl;
exit(1);
}
free(reply);
auto damage_handle = xcb_generate_id(connection.get());
xcb_damage_create(connection.get(), damage_handle, screen_of_display(connection.get(), 0)->root, XCB_DAMAGE_REPORT_LEVEL_RAW_RECTANGLES);
xcb_flush(connection.get());
auto xfd = xcb_get_file_descriptor(connection.get());
if (xfd <= 0)
{
cout << "invalid xcb file descriptor\n";
exit(1);
}
while (1)
{
auto tv = timeval{0, 20000};
fd_set fds;
FD_ZERO(&fds);
FD_SET(xfd, &fds);
int result = select(xfd + 1, &fds, nullptr, nullptr, &tv);
if (result == 0)
{
continue;
} else if (result < 0) {
cerr << "select failed with error: " << strerror(errno) << endl;
exit(1);
}
xcb_generic_event_t* event;
while ((event = xcb_poll_for_event(connection.get())))
{
// if (XCB_EVENT_RESPONSE_TYPE(event) != damageEvent)
if ((event->response_type & ~0x80) != (damageEvent + XCB_DAMAGE_NOTIFY))
{
free(event);
continue;
}
auto d = reinterpret_cast<xcb_damage_notify_event_t&>(*event);
cout << "--------- damage event ----------" << endl;
cout << "area: x: " << d.area.x << ", y: " << d.area.y << ", w: " << d.area.width << ", h: " << d.area.height << endl;
cout << "geometry: x: " << d.geometry.x << ", y: " << d.geometry.y << ", w: " << d.geometry.width << ", h: " << d.geometry.height << endl;
free(event);
}
}
xcb_damage_destroy(connection.get(), damage_handle);
return 0;
}