/*
* \brief Framebuffer session interface
* \author Norman Feske
* \date 2006-07-10
*/
/*
* Copyright (C) 2006-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _INCLUDE__FRAMEBUFFER_SESSION__FRAMEBUFFER_SESSION_H_
#define _INCLUDE__FRAMEBUFFER_SESSION__FRAMEBUFFER_SESSION_H_
#include
#include
#include
#include
#include
#include
#include
namespace Framebuffer {
struct Session;
struct Session_client;
using namespace Genode;
using Area = Surface_base::Area;
using Point = Surface_base::Point;
using Rect = Surface_base::Rect;
struct Mode
{
Area area;
bool alpha;
void print(Output &out) const { Genode::print(out, area); }
/*
* If using an alpha channel, the alpha buffer follows the pixel
* buffer. The alpha buffer is followed by an input-mask buffer.
*
* The input-mask buffer contains a byte value per texture pixel,
* which describes the policy of handling user input referring to the
* pixel. If set to zero, the input is passed through the view such
* that it can be handled by one of the subsequent views in the view
* stack. If set to one, the input is consumed by the view.
*/
void with_pixel_surface(auto &ds, auto const &fn) const
{
Surface surface { ds.bytes(), area };
fn(surface);
}
void with_alpha_bytes(auto &ds, auto const &fn) const
{
if (!alpha)
return;
size_t const offset = area.count()*sizeof(Pixel_rgb888);
ds.bytes().with_skipped_bytes(offset, [&] (Byte_range_ptr const &bytes) {
fn(bytes); });
}
void with_alpha_surface(auto &ds, auto const &fn) const
{
with_alpha_bytes(ds, [&] (Byte_range_ptr const &bytes) {
Surface surface { bytes, area };
fn(surface); });
}
void with_input_bytes(auto &ds, auto const &fn) const
{
if (!alpha)
return;
size_t const offset = area.count()*sizeof(Pixel_rgb888) + area.count();
ds.bytes().with_skipped_bytes(offset, [&] (Byte_range_ptr const &bytes) {
fn(bytes); });
}
void with_input_surface(auto &ds, auto const &fn) const
{
with_input_bytes(ds, [&] (Byte_range_ptr const &bytes) {
Surface surface { bytes, area };
fn(surface); });
}
size_t num_bytes() const
{
size_t const bytes_per_pixel =
sizeof(Pixel_rgb888) + alpha*(sizeof(Pixel_alpha8) + sizeof(Pixel_input8));
return area.count()*bytes_per_pixel;
}
};
struct Transfer
{
Rect from; /* source rectangle */
Point to; /* destination position */
/**
* Return true if transfer is applicable to 'mode'
*
* Pixels are transferred only if the source rectangle lies within
* the bounds of the framebuffer, and source does not overlap the
* destination.
*/
bool valid(Mode const &mode) const
{
Rect const fb { { }, mode.area };
Rect const dest { to, from.area };
return from.area.valid()
&& fb.contains(from.p1()) && fb.contains(from.p2())
&& fb.contains(dest.p1()) && fb.contains(dest.p2())
&& !Rect::intersect(from, dest).valid();
}
};
struct Blit_batch
{
static constexpr unsigned N = 4;
Transfer transfer[N];
};
}
struct Framebuffer::Session : Genode::Session
{
/**
* \noapi
*/
static const char *service_name() { return "Framebuffer"; }
/*
* A framebuffer session consumes a dataspace capability for the server's
* session-object allocation, a dataspace capability for the framebuffer
* dataspace, and its session capability.
*/
static constexpr unsigned CAP_QUOTA = 3;
using Client = Session_client;
virtual ~Session() { }
/**
* Request dataspace representing the logical frame buffer
*
* By calling this method, the framebuffer client enables the server
* to reallocate the framebuffer dataspace (e.g., on mode changes).
* Hence, prior calling this method, the client should make sure to
* have detached the previously requested dataspace from its local
* address space.
*/
virtual Dataspace_capability dataspace() = 0;
/**
* Request display-mode properties of the framebuffer ready to be
* obtained via the 'dataspace()' method
*/
virtual Mode mode() const = 0;
/**
* Register signal handler to be notified on mode changes
*
* The framebuffer server may support changing the display mode on the
* fly. For example, a virtual framebuffer presented in a window may
* get resized according to the window dimensions. By installing a
* signal handler for mode changes, the framebuffer client can respond
* to such changes. The new mode can be obtained using the 'mode()'
* method. However, from the client's perspective, the original mode
* stays in effect until the it calls 'dataspace()' again.
*/
virtual void mode_sigh(Signal_context_capability sigh) = 0;
/**
* Flush specified pixel region
*
* \param rect region to be updated on physical frame buffer
*/
virtual void refresh(Rect rect) = 0;
enum class Blit_result { OK, OVERLOADED };
/**
* Transfer pixel regions within the framebuffer
*/
virtual Blit_result blit(Blit_batch const &) = 0;
/**
* Define panning position of the framebuffer
*
* The panning position is the point within the framebuffer that
* corresponds to the top-left corner of the output. It is designated
* for implementing buffer flipping of double-buffered output, and for
* scrolling.
*/
virtual void panning(Point pos) = 0;
/**
* Register signal handler for refresh synchronization
*/
virtual void sync_sigh(Signal_context_capability) = 0;
/**
* Define the preferred source of sync signals
*
* In the presence of multiple capture clients at the GUI server, each
* client captures the GUI at independent refresh rates. Hence, there is
* no single source of sync signals but there can be multiple. From the
* application's perspective, the most adequate sync source may depend on
* the positions of the capture clients at the GUI server and the position
* of the application's view. By specifying a capture client's label as
* 'sync_sigh', the application can take an informed decision.
*/
virtual void sync_source(Session_label const &) = 0;
/*********************
** RPC declaration **
*********************/
GENODE_RPC(Rpc_dataspace, Dataspace_capability, dataspace);
GENODE_RPC(Rpc_mode, Mode, mode);
GENODE_RPC(Rpc_refresh, void, refresh, Rect);
GENODE_RPC(Rpc_blit, Blit_result, blit, Blit_batch const &);
GENODE_RPC(Rpc_panning, void, panning, Point);
GENODE_RPC(Rpc_mode_sigh, void, mode_sigh, Signal_context_capability);
GENODE_RPC(Rpc_sync_sigh, void, sync_sigh, Signal_context_capability);
GENODE_RPC(Rpc_sync_source, void, sync_source, Session_label const &);
GENODE_RPC_INTERFACE(Rpc_dataspace, Rpc_mode, Rpc_mode_sigh, Rpc_refresh,
Rpc_blit, Rpc_panning, Rpc_sync_sigh, Rpc_sync_source);
};
#endif /* _INCLUDE__FRAMEBUFFER_SESSION__FRAMEBUFFER_SESSION_H_ */