Skip to content

Commit 4d1e087

Browse files
committed
Merge branch 'main' into bugfix/3073
2 parents f954efc + 7f05753 commit 4d1e087

File tree

80 files changed

+1163
-1018
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

80 files changed

+1163
-1018
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ For other questions and discussion about the Mir project:
3939
the [\#mirserver](https://web.libera.chat/?channels=#mir-server) IRC channel on Libera.Chat.
4040

4141
For developer documentation, including installation and build instructions,
42-
see <https://mir-server.io/doc/index.html>.
42+
see <https://canonical-mir.readthedocs-hosted.com>.
4343

4444
# Copyright
4545
Copyright © Canonical Ltd.

doc/sphinx/.sphinx/requirements.txt

+12-11
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
1-
sphinx==7.1.2
2-
sphinx-autobuild
3-
sphinx-design
1+
breathe
2+
exhale
43
furo
5-
sphinx-tabs
6-
sphinx-reredirects
7-
pyspelling
8-
sphinxext-opengraph
94
lxd-sphinx-extensions
10-
sphinx-copybutton
115
myst-parser
12-
sphinxcontrib-jquery
6+
pillow
7+
pyspelling
8+
sphinx-autobuild
9+
sphinx-copybutton
10+
sphinx-design
1311
sphinx-notfound-page
14-
breathe
15-
exhale
12+
sphinx-reredirects
13+
sphinx-tabs
14+
sphinx==7.1.2
15+
sphinxcontrib-jquery
1616
sphinxcontrib-mermaid
17+
sphinxext-opengraph

examples/client/wayland_client.c

+90-23
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
#include <stdio.h>
2828
#include <stdbool.h>
2929
#include <signal.h>
30+
#include <poll.h>
31+
#include <sys/eventfd.h>
3032

3133
#include <wayland-client.h>
3234
#include <wayland-client-core.h>
@@ -218,11 +220,18 @@ find_free_buffer(draw_context* ctx)
218220
return NULL;
219221
}
220222

221-
static void draw_new_stuff(void* data, struct wl_callback* callback, uint32_t time);
223+
static int draw_signal;
224+
static void trigger_draw(void* data, struct wl_callback* callback, uint32_t time)
225+
{
226+
(void)data;
227+
(void)callback;
228+
(void)time;
229+
eventfd_write(draw_signal, 1);
230+
}
222231

223232
static const struct wl_callback_listener frame_listener =
224233
{
225-
.done = &draw_new_stuff
234+
.done = &trigger_draw
226235
};
227236

228237
static void update_free_buffers(void* data, struct wl_buffer* buffer)
@@ -239,22 +248,15 @@ static void update_free_buffers(void* data, struct wl_buffer* buffer)
239248
if (ctx->waiting_for_buffer)
240249
{
241250
struct wl_callback* fake_frame = wl_display_sync(ctx->display);
242-
wl_callback_add_listener(fake_frame, &frame_listener, ctx);
251+
wl_callback_add_listener(fake_frame, &frame_listener, NULL);
243252
}
244253

245254
ctx->waiting_for_buffer = false;
246255
}
247256

248-
static void draw_new_stuff(
249-
void* data,
250-
struct wl_callback* callback,
251-
uint32_t time)
257+
static void execute_draw(draw_context* ctx)
252258
{
253-
(void)time;
254259
static unsigned char current_value = 128;
255-
draw_context* ctx = data;
256-
257-
wl_callback_destroy(callback);
258260

259261
buffer* ctx_buffer = find_free_buffer(ctx);
260262
if (!ctx_buffer)
@@ -267,7 +269,7 @@ static void draw_new_stuff(
267269
++current_value;
268270

269271
ctx->new_frame_signal = wl_surface_frame(ctx->surface);
270-
wl_callback_add_listener(ctx->new_frame_signal, &frame_listener, ctx);
272+
wl_callback_add_listener(ctx->new_frame_signal, &frame_listener, NULL);
271273
wl_surface_attach(ctx->surface, ctx_buffer->buffer, 0, 0);
272274
wl_surface_commit(ctx->surface);
273275
}
@@ -419,12 +421,16 @@ static struct wl_output_listener const output_listener = {
419421
.scale = &output_scale,
420422
};
421423

422-
static volatile sig_atomic_t running = 0;
423-
static void shutdown(int signum)
424+
static int shutdown_signal;
425+
static void trigger_shutdown(int signum)
424426
{
425-
if (running)
427+
if (eventfd_write(shutdown_signal, 1) == -1)
428+
{
429+
printf("Failed to execute a shutdown");
430+
exit(-1);
431+
}
432+
else
426433
{
427-
running = 0;
428434
printf("Signal %d received. Good night.\n", signum);
429435
}
430436
}
@@ -482,6 +488,70 @@ static struct xdg_toplevel_listener const shell_toplevel_listener =
482488
handle_xdg_toplevel__capabilities,
483489
};
484490

491+
void run(struct wl_display* display, draw_context* ctx)
492+
{
493+
draw_signal = eventfd(0, EFD_SEMAPHORE);
494+
shutdown_signal = eventfd(0, EFD_CLOEXEC);
495+
496+
enum FdIndices {
497+
display_fd = 0,
498+
draw,
499+
shutdown,
500+
indices
501+
};
502+
503+
struct pollfd fds[indices] = {
504+
{wl_display_get_fd(display), POLLIN, 0},
505+
{draw_signal, POLLIN, 0},
506+
{shutdown_signal, POLLIN, 0},
507+
};
508+
509+
wl_display_roundtrip(display);
510+
wl_display_roundtrip(display);
511+
while (!(fds[shutdown].revents & (POLLIN | POLLERR)))
512+
{
513+
while (wl_display_prepare_read(display) != 0)
514+
{
515+
if (wl_display_dispatch_pending(display) == -1)
516+
{
517+
fprintf(stderr, "Failed to dispatch Wayland events\n");
518+
}
519+
}
520+
521+
if (poll(fds, indices, -1) == -1)
522+
{
523+
wl_display_cancel_read(display);
524+
}
525+
526+
if (fds[display_fd].revents & (POLLIN | POLLERR))
527+
{
528+
if (wl_display_read_events(display))
529+
{
530+
fprintf(stderr, "Failed to read Wayland events\n");
531+
}
532+
}
533+
else
534+
{
535+
wl_display_cancel_read(display);
536+
}
537+
538+
bool redraw = false;
539+
540+
if (fds[draw].revents & (POLLIN | POLLERR))
541+
{
542+
eventfd_t foo;
543+
eventfd_read(draw_signal, &foo);
544+
redraw = true;
545+
}
546+
547+
if (redraw)
548+
{
549+
execute_draw(ctx);
550+
wl_display_flush(display);
551+
}
552+
}
553+
}
554+
485555
int main(int argc, char** argv)
486556
{
487557
(void)argc;
@@ -518,23 +588,20 @@ int main(int argc, char** argv)
518588
xdg_toplevel_add_listener(shell_toplevel, &shell_toplevel_listener, ctx);
519589

520590
struct wl_callback* first_frame = wl_display_sync(display);
521-
wl_callback_add_listener(first_frame, &frame_listener, ctx);
591+
wl_callback_add_listener(first_frame, &frame_listener, NULL);
522592

523593
wl_output_add_listener(globals.output, &output_listener, NULL);
524-
525594
struct sigaction sig_handler_new;
526595
sigfillset(&sig_handler_new.sa_mask);
527596
sig_handler_new.sa_flags = 0;
528-
sig_handler_new.sa_handler = shutdown;
597+
sig_handler_new.sa_handler = trigger_shutdown;
529598

530599
sigaction(SIGINT, &sig_handler_new, NULL);
531600
sigaction(SIGTERM, &sig_handler_new, NULL);
532601
sigaction(SIGHUP, &sig_handler_new, NULL);
533602

534-
running = 1;
535-
536-
while (wl_display_dispatch(display) && running)
537-
;
603+
run(display, ctx);
538604

539605
return 0;
540606
}
607+

include/platform/mir/graphics/display_buffer.h

+52-3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#ifndef MIR_GRAPHICS_DISPLAY_BUFFER_H_
1818
#define MIR_GRAPHICS_DISPLAY_BUFFER_H_
1919

20+
#include "mir/graphics/platform.h"
2021
#include <mir/geometry/rectangle.h>
2122
#include <mir/graphics/renderable.h>
2223
#include <mir_toolkit/common.h>
@@ -61,9 +62,9 @@ class DisplayBuffer
6162
/** The size in pixels of the underlying display */
6263
virtual auto pixel_size() const -> geometry::Size = 0;
6364

64-
/** This will render renderlist to the screen and post the result to the
65+
/** This will render renderlist to the screen and post the result to the
6566
* screen if there is a hardware optimization that can be done.
66-
* \param [in] renderlist
67+
* \param [in] renderlist
6768
* The renderables that should appear on the screen if the hardware
6869
* is capable of optmizing that list somehow. If what you want
6970
* displayed on the screen cannot be represented by a RenderableList,
@@ -98,8 +99,56 @@ class DisplayBuffer
9899
*/
99100
virtual glm::mat2 transformation() const = 0;
100101

101-
virtual auto display_provider() const -> std::shared_ptr<DisplayInterfaceProvider> = 0;
102+
/**
103+
* Attempt to acquire a platform-specific provider from this DisplayBuffer
104+
*
105+
* Any given platform is not guaranteed to implement any specific interface,
106+
* and the set of supported interfaces may depend on the runtime environment.
107+
*
108+
* Since this may result in a runtime probe the call may be costly, and the
109+
* result should be saved rather than re-acquiring an interface each time.
110+
*
111+
* \tparam Allocator
112+
* \return On success: a non-null pointer to an Allocator implementation.
113+
* The lifetime of this Allocator implementation is bound
114+
* to that of the parent DisplayBuffer.
115+
* On failure: nullptr
116+
*/
117+
template<typename Allocator>
118+
auto acquire_allocator() -> Allocator*
119+
{
120+
static_assert(
121+
std::is_convertible_v<Allocator*, DisplayAllocator*>,
122+
"Can only acquire a DisplayAllocator; Provider must implement DisplayAllocator");
123+
124+
if (auto const base_interface = maybe_create_allocator(typename Allocator::Tag{}))
125+
{
126+
if (auto const requested_interface = dynamic_cast<Allocator*>(base_interface))
127+
{
128+
return requested_interface;
129+
}
130+
BOOST_THROW_EXCEPTION((std::logic_error{
131+
"Implementation error! Platform returned object that does not support requested interface"}));
132+
}
133+
return nullptr;
134+
}
135+
102136
protected:
137+
/**
138+
* Acquire a specific hardware interface
139+
*
140+
* This should perform any runtime checks necessary to verify the requested interface is
141+
* expected to work and return a pointer to an implementation of that interface.
142+
*
143+
* \param type_tag [in] An instance of the Tag type for the requested interface.
144+
* Implementations are expected to dynamic_cast<> this to
145+
* discover the specific interface being requested.
146+
* \return A pointer to an implementation of the DisplayAllocator-derived
147+
* interface that corresponds to the most-derived type of tag_type.
148+
*/
149+
virtual auto maybe_create_allocator(DisplayAllocator::Tag const& type_tag)
150+
-> DisplayAllocator* = 0;
151+
103152
DisplayBuffer() = default;
104153
DisplayBuffer(DisplayBuffer const& c) = delete;
105154
DisplayBuffer& operator=(DisplayBuffer const& c) = delete;

0 commit comments

Comments
 (0)