layer: Add Reply audo-delete helper for XCB replies

This commit is contained in:
Joshua Ashton 2023-01-02 06:08:32 +00:00
parent 89456dd976
commit ece20d0120
2 changed files with 23 additions and 35 deletions

View file

@ -280,11 +280,11 @@ namespace GamescopeWSILayer {
if ((res = pDispatch->GetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, pSurfaceCapabilities)) != VK_SUCCESS)
return res;
VkExtent2D currentExtent = {};
if ((res = getCurrentExtent(gamescopeSurface->connection, gamescopeSurface->window, &currentExtent)) != VK_SUCCESS)
return res;
auto rect = xcb::getWindowRect(gamescopeSurface->connection, gamescopeSurface->window);
if (!rect)
return VK_ERROR_SURFACE_LOST_KHR;
pSurfaceCapabilities->currentExtent = currentExtent;
pSurfaceCapabilities->currentExtent = rect->extent;
pSurfaceCapabilities->minImageCount = getMinImageCount();
return VK_SUCCESS;
@ -455,17 +455,6 @@ namespace GamescopeWSILayer {
return s_isRunningUnderGamescope;
}
static VkResult getCurrentExtent(xcb_connection_t* xcb_conn, xcb_window_t window, VkExtent2D* pExtent) {
xcb_get_geometry_cookie_t geom_cookie = xcb_get_geometry(xcb_conn, window);
xcb_get_geometry_reply_t* geom = xcb_get_geometry_reply(xcb_conn, geom_cookie, nullptr);
if (!geom)
return VK_ERROR_SURFACE_LOST_KHR;
*pExtent = VkExtent2D{ geom->width, geom->height };
free(geom);
return VK_SUCCESS;
}
static uint32_t getMinImageCount() {
{
const char *overrideStr = std::getenv("GAMESCOPE_WSI_MIN_IMAGE_COUNT");

View file

@ -7,15 +7,24 @@
namespace xcb {
struct ReplyDeleter {
template <typename T>
void operator()(T* ptr) const {
free(const_cast<std::remove_const_t<T>*>(ptr));
}
};
template <typename T>
using Reply = std::unique_ptr<T, ReplyDeleter>;
static std::optional<xcb_atom_t> getAtom(xcb_connection_t* connection, std::string_view name) {
xcb_intern_atom_cookie_t cookie = xcb_intern_atom(connection, false, name.length(), name.data());
xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(connection, cookie, nullptr);
auto reply = Reply<xcb_intern_atom_reply_t>{ xcb_intern_atom_reply(connection, cookie, nullptr) };
if (!reply) {
fprintf(stderr, "[Gamescope WSI] Failed to get xcb atom.\n");
return std::nullopt;
}
xcb_atom_t atom = reply->atom;
free(reply);
return atom;
}
@ -26,7 +35,7 @@ namespace xcb {
xcb_screen_t* screen = xcb_setup_roots_iterator(xcb_get_setup(connection)).data;
xcb_get_property_cookie_t cookie = xcb_get_property(connection, false, screen->root, atom, XCB_ATOM_CARDINAL, 0, sizeof(T) / sizeof(uint32_t));
xcb_get_property_reply_t* reply = xcb_get_property_reply(connection, cookie, nullptr);
auto reply = Reply<xcb_get_property_reply_t>{ xcb_get_property_reply(connection, cookie, nullptr) };
if (!reply) {
fprintf(stderr, "[Gamescope WSI] Failed to read T root window property.\n");
return std::nullopt;
@ -34,12 +43,10 @@ namespace xcb {
if (reply->type != XCB_ATOM_CARDINAL) {
fprintf(stderr, "[Gamescope WSI] Atom of T was wrong type. Expected XCB_ATOM_CARDINAL.\n");
free(reply);
return std::nullopt;
}
T value = *reinterpret_cast<const T *>(xcb_get_property_value(reply));
free(reply);
T value = *reinterpret_cast<const T *>(xcb_get_property_value(reply.get()));
return value;
}
@ -55,26 +62,23 @@ namespace xcb {
static std::optional<xcb_window_t> getToplevelWindow(xcb_connection_t* connection, xcb_window_t window) {
for (;;) {
xcb_query_tree_cookie_t cookie = xcb_query_tree(connection, window);
xcb_query_tree_reply_t* reply = xcb_query_tree_reply(connection, cookie, nullptr);
auto reply = Reply<xcb_query_tree_reply_t>{ xcb_query_tree_reply(connection, cookie, nullptr) };
if (!reply) {
fprintf(stderr, "[Gamescope WSI] getToplevelWindow: xcb_query_tree failed for window 0x%x.\n", window);
return std::nullopt;
}
if (reply->root == reply->parent) {
free(reply);
if (reply->root == reply->parent)
return window;
}
window = reply->parent;
free(reply);
}
}
static std::optional<VkRect2D> getWindowRect(xcb_connection_t* connection, xcb_window_t window) {
xcb_get_geometry_cookie_t cookie = xcb_get_geometry(connection, window);
xcb_get_geometry_reply_t* reply = xcb_get_geometry_reply(connection, cookie, nullptr);
auto reply = Reply<xcb_get_geometry_reply_t>{ xcb_get_geometry_reply(connection, cookie, nullptr) };
if (!reply) {
fprintf(stderr, "[Gamescope WSI] getWindowRect: xcb_get_geometry failed for window 0x%x.\n", window);
return std::nullopt;
@ -85,7 +89,6 @@ namespace xcb {
.extent = { reply->width, reply->height },
};
free(reply);
return rect;
}
@ -110,7 +113,7 @@ namespace xcb {
VkExtent2D largestExtent = {};
xcb_query_tree_cookie_t cookie = xcb_query_tree(connection, window);
xcb_query_tree_reply_t* reply = xcb_query_tree_reply(connection, cookie, nullptr);
auto reply = Reply<xcb_query_tree_reply_t>{ xcb_query_tree_reply(connection, cookie, nullptr) };
if (!reply) {
fprintf(stderr, "[Gamescope WSI] getLargestObscuringWindowSize: xcb_query_tree failed for window 0x%x.\n", window);
@ -123,12 +126,12 @@ namespace xcb {
return std::nullopt;
}
xcb_window_t* children = xcb_query_tree_children(reply);
xcb_window_t* children = xcb_query_tree_children(reply.get());
for (uint32_t i = 0; i < reply->children_len; i++) {
xcb_window_t child = children[i];
xcb_get_window_attributes_cookie_t attributeCookie = xcb_get_window_attributes(connection, child);
xcb_get_window_attributes_reply_t *attributeReply = xcb_get_window_attributes_reply(connection, attributeCookie, nullptr);
auto attributeReply = Reply<xcb_get_window_attributes_reply_t>{ xcb_get_window_attributes_reply(connection, attributeCookie, nullptr) };
const bool obscuring =
attributeReply &&
@ -141,12 +144,8 @@ namespace xcb {
largestExtent = max(largestExtent, clippedRect.extent);
}
}
free(attributeReply);
}
free(reply);
return largestExtent;
}