Skip to content

Commit

Permalink
feat: support wlr_output_management_unstable_v1 version 4
Browse files Browse the repository at this point in the history
This version comes with support for adaptive sync.
  • Loading branch information
romangg committed Mar 31, 2023
1 parent 514c8ff commit 52ed043
Show file tree
Hide file tree
Showing 13 changed files with 124 additions and 7 deletions.
10 changes: 9 additions & 1 deletion autotests/client/wlr_output_management.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ void TestWlrOutputManagement::init()
auto state = first_output->get_state();
state.mode = m1;
state.geometry = QRectF(QPointF(0, 1920), QSizeF(1024, 768));
state.adaptive_sync = true;
first_output->set_state(state);
server.globals.outputs.push_back(std::move(first_output));
server.globals.output_manager->commit_changes();
Expand Down Expand Up @@ -222,7 +223,7 @@ void TestWlrOutputManagement::test_add_remove_output()
QCOMPARE(client.wl_output_spy->size(), 1);

// The wlr head receives the changed properties. Client-side no atomic changes at the moment.
QTRY_COMPARE(head_changed_spy.size(), 5);
QTRY_COMPARE(head_changed_spy.size(), 6);

// Add one more output which is already enabled.
server.globals.outputs.emplace_back(
Expand Down Expand Up @@ -282,6 +283,7 @@ void TestWlrOutputManagement::test_properties()
QCOMPARE(wlr_head1->position(), QPoint(0, 0));
QCOMPARE(wlr_head1->transform(), Clt::WlrOutputHeadV1::Transform::Normal);
QCOMPARE(wlr_head1->scale(), 1);
QVERIFY(!wlr_head1->adaptive_sync());

// The first output is not yet enabled. Do this now. All data is sent.
auto state = server.globals.outputs.front()->get_state();
Expand All @@ -306,6 +308,7 @@ void TestWlrOutputManagement::test_properties()
QCOMPARE(wlr_head1->position(), QPoint(0, 1920));
QCOMPARE(wlr_head1->transform(), Clt::WlrOutputHeadV1::Transform::Normal);
QCOMPARE(wlr_head1->scale(), 1);
QVERIFY(wlr_head1->adaptive_sync());

// Add one more output which is already enabled.
Srv::output_metadata meta{
Expand All @@ -322,6 +325,7 @@ void TestWlrOutputManagement::test_properties()
state.enabled = true;
state.geometry = QRectF(QPointF(1920, 1920), QSizeF(400, 300));
state.transform = Srv::output_transform::flipped_180;
state.adaptive_sync = true;
server_output->set_state(state);
server.globals.output_manager->commit_changes();

Expand All @@ -347,6 +351,7 @@ void TestWlrOutputManagement::test_properties()
QCOMPARE(wlr_head2->position(), QPoint(1920, 1920));
QCOMPARE(wlr_head2->transform(), Clt::WlrOutputHeadV1::Transform::Flipped180);
QCOMPARE(wlr_head2->scale(), 2);
QVERIFY(wlr_head2->adaptive_sync());
}

void TestWlrOutputManagement::test_configuration()
Expand Down Expand Up @@ -399,6 +404,7 @@ void TestWlrOutputManagement::test_configuration()
QCOMPARE(wlr_head2->position(), QPoint(1920, 1920));
QCOMPARE(wlr_head2->transform(), Clt::WlrOutputHeadV1::Transform::Flipped180);
QCOMPARE(wlr_head2->scale(), 2);
QVERIFY(!wlr_head2->adaptive_sync());

auto config = std::unique_ptr<Clt::WlrOutputConfigurationV1>{
client.output_manager->createConfiguration()};
Expand All @@ -411,6 +417,7 @@ void TestWlrOutputManagement::test_configuration()
config->setPosition(wlr_head2, QPoint(0, 0));
config->setTransform(wlr_head2, Clt::WlrOutputHeadV1::Transform::Rotated90);
config->setScale(wlr_head2, 1);
config->set_adaptive_sync(wlr_head2, true);
config->apply();

QSignalSpy config_apply_spy(server.globals.output_manager->wlr_manager_v1.get(),
Expand All @@ -429,6 +436,7 @@ void TestWlrOutputManagement::test_configuration()
QCOMPARE(config_head->get_state().mode, server.modes.at(1));
QCOMPARE(config_head->get_state().geometry, QRect(QPoint(0, 0), QSize(768, 1024)));
QCOMPARE(config_head->get_state().transform, Srv::output_transform::rotated_90);
QVERIFY(config_head->get_state().adaptive_sync);

server_config->send_succeeded();

Expand Down
1 change: 1 addition & 0 deletions server/output.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ struct output_state {

// Automatically calculated on setter call.
int client_scale = 1;
bool adaptive_sync{false};
};

/**
Expand Down
16 changes: 16 additions & 0 deletions server/wlr_output_configuration_head_v1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ struct zwlr_output_configuration_head_v1_interface const
set_position_callback,
set_transform_callback,
set_scale_callback,
set_adaptive_sync_callback,
};

bool is_portrait_transform(output_transform tr)
Expand Down Expand Up @@ -130,6 +131,21 @@ void wlr_output_configuration_head_v1::Private::set_scale_callback(wl_client* /*
priv->state.geometry.setSize(estimate_logical_size(priv->state, priv->scale));
}

void wlr_output_configuration_head_v1::Private::set_adaptive_sync_callback(wl_client* /*wlClient*/,
wl_resource* wlResource,
uint32_t wlState)
{
auto priv = get_handle(wlResource)->d_ptr;
if (wlState != ZWLR_OUTPUT_HEAD_V1_ADAPTIVE_SYNC_STATE_DISABLED
&& wlState != ZWLR_OUTPUT_HEAD_V1_ADAPTIVE_SYNC_STATE_ENABLED) {
priv->postError(ZWLR_OUTPUT_CONFIGURATION_HEAD_V1_ERROR_INVALID_ADAPTIVE_SYNC_STATE,
"adaptive sync state out of range");
return;
}

priv->state.adaptive_sync = wlState == ZWLR_OUTPUT_HEAD_V1_ADAPTIVE_SYNC_STATE_ENABLED;
}

wlr_output_configuration_head_v1::wlr_output_configuration_head_v1(
Client* client,
uint32_t version,
Expand Down
2 changes: 2 additions & 0 deletions server/wlr_output_configuration_head_v1_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ class wlr_output_configuration_head_v1::Private
set_transform_callback(wl_client* wlClient, wl_resource* wlResource, int32_t wlTransform);
static void
set_scale_callback(wl_client* wlClient, wl_resource* wlResource, wl_fixed_t wlScale);
static void
set_adaptive_sync_callback(wl_client* wlClient, wl_resource* wlResource, uint32_t wlState);

static const struct zwlr_output_configuration_head_v1_interface s_interface;
};
Expand Down
18 changes: 18 additions & 0 deletions server/wlr_output_head_v1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,13 @@ void wlr_output_head_v1::broadcast()
current_scale = scale;
manager.d_ptr->changed = true;
}

if (published.state.adaptive_sync != pending.state.adaptive_sync || !published.state.enabled) {
for (auto res : resources) {
res->send_adaptive_sync(pending.state.adaptive_sync);
}
manager.d_ptr->changed = true;
}
}

wlr_output_head_v1_res::Private::Private(Client* client,
Expand Down Expand Up @@ -172,6 +179,7 @@ void wlr_output_head_v1_res::send_mutable_data(output_state const& data) const
send_position(data.geometry.topLeft().toPoint());
send_transform(data.transform);
send_scale(estimate_scale(data));
send_adaptive_sync(data.adaptive_sync);
}

void wlr_output_head_v1_res::send_enabled(bool enabled) const
Expand Down Expand Up @@ -203,4 +211,14 @@ void wlr_output_head_v1_res::send_scale(double scale) const
d_ptr->send<zwlr_output_head_v1_send_scale>(wl_fixed_from_double(scale));
}

void wlr_output_head_v1_res::send_adaptive_sync(bool is_adaptive) const
{
if (d_ptr->version < ZWLR_OUTPUT_HEAD_V1_ADAPTIVE_SYNC_SINCE_VERSION) {
return;
}
d_ptr->send<zwlr_output_head_v1_send_adaptive_sync>(
is_adaptive ? ZWLR_OUTPUT_HEAD_V1_ADAPTIVE_SYNC_STATE_ENABLED
: ZWLR_OUTPUT_HEAD_V1_ADAPTIVE_SYNC_STATE_DISABLED);
}

}
1 change: 1 addition & 0 deletions server/wlr_output_head_v1_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ class wlr_output_head_v1_res : public QObject
void send_position(QPoint const& pos) const;
void send_transform(output_transform transform) const;
void send_scale(double scale) const;
void send_adaptive_sync(bool is_adaptive) const;

class Private;
Private* d_ptr;
Expand Down
2 changes: 1 addition & 1 deletion server/wlr_output_manager_v1_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ namespace Wrapland::Server
class wlr_output_configuration_v1;
class wlr_output_head_v1;

constexpr uint32_t wlr_output_manager_v1_version = 3;
constexpr uint32_t wlr_output_manager_v1_version = 4;
using wlr_output_manager_v1_global
= Wayland::Global<wlr_output_manager_v1, wlr_output_manager_v1_version>;
using wlr_output_manager_v1_bind = Wayland::Bind<wlr_output_manager_v1_global>;
Expand Down
36 changes: 32 additions & 4 deletions src/client/protocols/wlr-output-management-unstable-v1.xml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
interface version number is reset.
</description>

<interface name="zwlr_output_manager_v1" version="3">
<interface name="zwlr_output_manager_v1" version="4">
<description summary="output device configuration manager">
This interface is a manager that allows reading and writing the current
output device configuration.
Expand Down Expand Up @@ -125,7 +125,7 @@
</event>
</interface>

<interface name="zwlr_output_head_v1" version="3">
<interface name="zwlr_output_head_v1" version="4">
<description summary="output device">
A head is an output device. The difference between a wl_output object and
a head is that heads are advertised even if they are turned off. A head
Expand Down Expand Up @@ -338,6 +338,22 @@
object.
</description>
</request>

<!-- Version 4 additions -->

<enum name="adaptive_sync_state" since="4">
<entry name="disabled" value="0" summary="adaptive sync is disabled"/>
<entry name="enabled" value="1" summary="adaptive sync is enabled"/>
</enum>

<event name="adaptive_sync" since="4">
<description summary="current adaptive sync state">
This event describes whether adaptive sync is currently enabled for
the head or not. Adaptive sync is also known as Variable Refresh
Rate or VRR.
</description>
<arg name="state" type="uint" enum="adaptive_sync_state"/>
</event>
</interface>

<interface name="zwlr_output_mode_v1" version="3">
Expand Down Expand Up @@ -395,7 +411,7 @@
</request>
</interface>

<interface name="zwlr_output_configuration_v1" version="3">
<interface name="zwlr_output_configuration_v1" version="4">
<description summary="output configuration">
This object is used by the client to describe a full output configuration.

Expand Down Expand Up @@ -513,7 +529,7 @@
</request>
</interface>

<interface name="zwlr_output_configuration_head_v1" version="3">
<interface name="zwlr_output_configuration_head_v1" version="4">
<description summary="head configuration">
This object is used by the client to update a single head's configuration.

Expand All @@ -526,6 +542,8 @@
<entry name="invalid_custom_mode" value="3" summary="mode is invalid"/>
<entry name="invalid_transform" value="4" summary="transform value outside enum"/>
<entry name="invalid_scale" value="5" summary="scale negative or zero"/>
<entry name="invalid_adaptive_sync_state" value="6" since="4"
summary="invalid enum value used in the set_adaptive_sync request"/>
</enum>

<request name="set_mode">
Expand Down Expand Up @@ -569,5 +587,15 @@
</description>
<arg name="scale" type="fixed"/>
</request>

<!-- Version 4 additions -->

<request name="set_adaptive_sync" since="4">
<description summary="enable/disable adaptive sync">
This request enables/disables adaptive sync. Adaptive sync is also
known as Variable Refresh Rate or VRR.
</description>
<arg name="state" type="uint" enum="zwlr_output_head_v1.adaptive_sync_state"/>
</request>
</interface>
</protocol>
2 changes: 1 addition & 1 deletion src/client/registry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ static QMap<Registry::Interface, SuppertedInterfaceData> const s_interfaces = {
{
Registry::Interface::WlrOutputManagerV1,
{
3,
4,
QByteArrayLiteral("zwlr_output_manager_v1"),
&zwlr_output_manager_v1_interface,
&Registry::wlrOutputManagerV1Announced,
Expand Down
21 changes: 21 additions & 0 deletions src/client/wlr_output_configuration_v1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ struct ConfigurationHead {
bool transformSet = false;
double scale = 1.;
bool scaleSet = false;
bool adapt_sync{false};
bool adapt_sync_set{false};
};

class Q_DECL_HIDDEN WlrOutputConfigurationV1::Private
Expand Down Expand Up @@ -200,6 +202,13 @@ void WlrOutputConfigurationV1::Private::send()
zwlr_output_configuration_head_v1_set_scale(head->native,
wl_fixed_from_double(head->scale));
}

if (head->adapt_sync_set) {
zwlr_output_configuration_head_v1_set_adaptive_sync(
head->native,
head->adapt_sync ? ZWLR_OUTPUT_HEAD_V1_ADAPTIVE_SYNC_STATE_ENABLED
: ZWLR_OUTPUT_HEAD_V1_ADAPTIVE_SYNC_STATE_DISABLED);
}
}
}

Expand Down Expand Up @@ -277,6 +286,18 @@ void WlrOutputConfigurationV1::setScale(WlrOutputHeadV1* head, double scale)
configurationHead->scaleSet = true;
}

void WlrOutputConfigurationV1::set_adaptive_sync(WlrOutputHeadV1* head, bool enable)
{
auto configurationHead = d->getConfigurationHead(head);
if (zwlr_output_configuration_head_v1_get_version(configurationHead->native)
< ZWLR_OUTPUT_CONFIGURATION_HEAD_V1_SET_ADAPTIVE_SYNC_SINCE_VERSION) {
return;
}

configurationHead->adapt_sync = enable;
configurationHead->adapt_sync_set = true;
}

void WlrOutputConfigurationV1::test()
{
d->send();
Expand Down
2 changes: 2 additions & 0 deletions src/client/wlr_output_configuration_v1.h
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,8 @@ class WRAPLANDCLIENT_EXPORT WlrOutputConfigurationV1 : public QObject
*/
void setScale(WlrOutputHeadV1* head, double scale);

void set_adaptive_sync(WlrOutputHeadV1* head, bool enable);

/**
* Check if current configuration is valid. Either succeeded() or failed() will be emitted
* later on as a result of this call.
Expand Down
19 changes: 19 additions & 0 deletions src/client/wlr_output_manager_v1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,7 @@ class Q_DECL_HIDDEN WlrOutputHeadV1::Private
static void modelCallback(void* data, zwlr_output_head_v1* head, char const* model);
static void
serialNumberCallback(void* data, zwlr_output_head_v1* head, char const* serialNumber);
static void adaptive_sync_callback(void* data, zwlr_output_head_v1* head, uint32_t state);

WlrOutputHeadV1* q;
static const struct zwlr_output_head_v1_listener s_listener;
Expand All @@ -296,6 +297,7 @@ class Q_DECL_HIDDEN WlrOutputHeadV1::Private
Transform transform{Transform::Normal};
bool enabled{false};
double scale{1.};
bool adapt_sync{false};

QString make;
QString model;
Expand All @@ -322,6 +324,7 @@ const zwlr_output_head_v1_listener WlrOutputHeadV1::Private::s_listener = {
makeCallback,
modelCallback,
serialNumberCallback,
adaptive_sync_callback,
};

void WlrOutputHeadV1::Private::nameCallback(void* data, zwlr_output_head_v1* head, char const* name)
Expand Down Expand Up @@ -514,6 +517,17 @@ void WlrOutputHeadV1::Private::serialNumberCallback(void* data,
Q_EMIT d->q->changed();
}

void WlrOutputHeadV1::Private::adaptive_sync_callback(void* data,
zwlr_output_head_v1* head,
uint32_t state)
{
auto d = reinterpret_cast<Private*>(data);
Q_ASSERT(d->outputHead == head);

d->adapt_sync = state == ZWLR_OUTPUT_HEAD_V1_ADAPTIVE_SYNC_STATE_ENABLED;
Q_EMIT d->q->changed();
}

WlrOutputHeadV1::Private::Private(WlrOutputHeadV1* q, zwlr_output_head_v1* head)
: q(q)
{
Expand Down Expand Up @@ -579,6 +593,11 @@ double WlrOutputHeadV1::scale() const
return d->scale;
}

bool WlrOutputHeadV1::adaptive_sync() const
{
return d->adapt_sync;
}

QVector<WlrOutputModeV1*> WlrOutputHeadV1::modes() const
{
QVector<WlrOutputModeV1*> ret;
Expand Down
1 change: 1 addition & 0 deletions src/client/wlr_output_manager_v1.h
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ class WRAPLANDCLIENT_EXPORT WlrOutputHeadV1 : public QObject
QPoint position() const;
Transform transform() const;
double scale() const;
bool adaptive_sync() const;

operator zwlr_output_head_v1*();
operator zwlr_output_head_v1*() const;
Expand Down

0 comments on commit 52ed043

Please sign in to comment.