Mir
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
render_surfaces.cpp: A simple program using the mir library.

Table of Contents

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 conf{argc, argv};
{
cursor = conf.the_cursor();
input_is_on = conf.input_is_on();
});

RenderSurfacesServerConfiguration

The configuration stubs out client connectivity and input.

// Stub out server connectivity.
std::shared_ptr<mf::Connector> the_connector() override
{
struct NullConnector : public mf::Connector
{
void start() {}
void stop() {}
int client_socket_fd() const override { return 0; }
void remove_endpoint() const override { }
};
return std::make_shared<NullConnector>();
}

it also provides a bespoke buffer initializer

// Override for a bespoke buffer initializer
std::shared_ptr<mg::BufferInitializer> the_buffer_initializer() override
{
class RenderResourcesBufferInitializer : public mg::BufferInitializer
{
public:
RenderResourcesBufferInitializer(std::unique_ptr<mg::GLContext> gl_context)
: gl_context{std::move(gl_context)}
{
}
void operator()(mg::Buffer& buffer)
{
auto using_gl_context = mir::raii::paired_calls(
[this] { gl_context->make_current(); },
[this] { gl_context->release_current(); });
mt::ImageRenderer img_renderer{mir_image.pixel_data,
geom::Size{mir_image.width, mir_image.height},
mir_image.bytes_per_pixel};
brt.make_current();
img_renderer.render();
}
private:
std::unique_ptr<mg::GLContext> const gl_context;
};
return std::make_shared<RenderResourcesBufferInitializer>(the_display()->create_gl_context());
}

and a bespoke display buffer compositor

// Decorate the DefaultDisplayBufferCompositor in order to move surfaces.
std::shared_ptr<mc::DisplayBufferCompositorFactory> the_display_buffer_compositor_factory() override
{
class RenderSurfacesDisplayBufferCompositor : public mc::DisplayBufferCompositor
{
public:
RenderSurfacesDisplayBufferCompositor(
std::unique_ptr<DisplayBufferCompositor> db_compositor,
std::vector<Moveable>& moveables)
: db_compositor{std::move(db_compositor)},
moveables(moveables),
frames{0}
{
}
bool composite()
{
while (!created) std::this_thread::yield();
animate_cursor();
stop_watch.stop();
if (stop_watch.elapsed_seconds_since_last_restart() >= 1)
{
std::cout << "FPS: " << frames << " Frame Time: " << 1.0 / frames << std::endl;
frames = 0;
stop_watch.restart();
}
glClearColor(0.0, 1.0, 0.0, 1.0);
db_compositor->composite();
for (auto& m : moveables)
m.step();
frames++;
return false;
}
private:
std::unique_ptr<DisplayBufferCompositor> const db_compositor;
StopWatch stop_watch;
std::vector<Moveable>& moveables;
uint32_t frames;
};
class RenderSurfacesDisplayBufferCompositorFactory : public mc::DisplayBufferCompositorFactory
{
public:
RenderSurfacesDisplayBufferCompositorFactory(
std::shared_ptr<mc::DisplayBufferCompositorFactory> const& factory,
std::vector<Moveable>& moveables)
: factory{factory},
moveables(moveables)
{
}
std::unique_ptr<mc::DisplayBufferCompositor> create_compositor_for(mg::DisplayBuffer& display_buffer)
{
auto compositor = factory->create_compositor_for(display_buffer);
auto raw = new RenderSurfacesDisplayBufferCompositor(
std::move(compositor), moveables);
return std::unique_ptr<RenderSurfacesDisplayBufferCompositor>(raw);
}
private:
std::shared_ptr<mc::DisplayBufferCompositorFactory> const factory;
std::vector<Moveable>& moveables;
};
return std::make_shared<RenderSurfacesDisplayBufferCompositorFactory>(
moveables);
}

Utility classes

For smooth animation we need to track time and move surfaces accordingly

StopWatch

// tracks elapsed time - for animation.
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

// Adapter to support movement of surfaces.
class Moveable
{
public:
Moveable() {}
Moveable(std::shared_ptr<msh::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;
if (new_x < 0.0 || new_x + w > display_size.width.as_uint32_t())
{
dx = -dx;
should_update = false;
}
if (new_y < 0.0 || new_y + h > display_size.height.as_uint32_t())
{
dy = -dy;
should_update = false;
}
if (should_update)
{
surface->move_to({new_x, new_y});
x = new_x;
y = 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<msh::Surface> surface;
geom::Size display_size;
float x;
float y;
float w;
float h;
float dx;
float dy;
StopWatch stop_watch;
glm::vec3 rotation_axis;
float alpha_offset;
};

Copyright © 2012,2013 Canonical Ltd.
Generated on Fri Apr 11 21:14:53 UTC 2014