render_surfaces shows the use of mir to render some moving surfaces
main()
The main() function uses a RenderSurfacesServerConfiguration to initialize and run mir.
RenderSurfacesServerConfiguration
The configuration stubs out client connectivity and input.
it also provides a bespoke display buffer compositor
wrap_display_buffer_compositor_factory([this](std::shared_ptr<mc::DisplayBufferCompositorFactory> const& wrapped)
{
return std::make_shared<RenderSurfacesDisplayBufferCompositorFactory>(
wrapped,
moveables);
});
Utility classes
For smooth animation we need to track time and move surfaces accordingly
StopWatch
class StopWatch
{
public:
StopWatch() : start(
std::chrono::high_resolution_clock::now()),
last(start),
now(last)
{
}
void stop()
{
now = std::chrono::high_resolution_clock::now();
}
double elapsed_seconds_since_start()
{
auto elapsed = now - start;
float elapsed_sec = std::chrono::duration_cast<std::chrono::microseconds>(elapsed).count() / 1000000.0f;
return elapsed_sec;
}
double elapsed_seconds_since_last_restart()
{
auto elapsed = now - last;
float elapsed_sec = std::chrono::duration_cast<std::chrono::microseconds>(elapsed).count() / 1000000.0f;
return elapsed_sec;
}
void restart()
{
std::swap(last, now);
}
private:
std::chrono::high_resolution_clock::time_point start;
std::chrono::high_resolution_clock::time_point last;
std::chrono::high_resolution_clock::time_point now;
};
Moveable
class Moveable
{
public:
Moveable() {}
Moveable(std::shared_ptr<ms::Surface>
const& s,
const geom::Size& display_size,
float dx,
float dy,
const glm::vec3& rotation_axis,
float alpha_offset)
: surface(s), display_size(display_size),
x{
static_cast<float>(s->top_left().x.as_uint32_t())},
y{
static_cast<float>(s->top_left().y.as_uint32_t())},
w{static_cast<float>(s->size().width.as_uint32_t())},
h{static_cast<float>(s->size().height.as_uint32_t())},
dx{dx},
dy{dy},
rotation_axis(rotation_axis),
alpha_offset{alpha_offset}
{
}
void step()
{
stop_watch.stop();
float elapsed_sec = stop_watch.elapsed_seconds_since_last_restart();
float total_elapsed_sec = stop_watch.elapsed_seconds_since_start();
stop_watch.restart();
bool should_update = true;
float new_x =
x + elapsed_sec *
dx;
float new_y =
y + elapsed_sec *
dy;
{
should_update = false;
}
{
should_update = false;
}
if (should_update)
{
surface->move_to({new_x, new_y});
}
glm::mat4 trans = glm::rotate(glm::mat4(1.0f),
glm::radians(total_elapsed_sec * 120.0f),
rotation_axis);
surface->set_transformation(trans);
float const alpha_amplitude = (1.0f - min_alpha) / 2.0f;
surface->set_alpha(min_alpha + alpha_amplitude +
alpha_amplitude *
sin(alpha_offset + 2 * M_PI * total_elapsed_sec /
3.0));
}
private:
std::shared_ptr<ms::Surface> surface;
float w;
float h;
StopWatch stop_watch;
glm::vec3 rotation_axis;
float alpha_offset;
};