Skip to content

Commit

Permalink
support page flipping of overlay and primary plane framebuffers
Browse files Browse the repository at this point in the history
Support allocating multiple framebuffers per plane with plane_create_buffered().
Then, the new plane_flip() can be called to switch between those buffers safely
in order to set a new front buffer to the plane.  This setup supports any number
of buffering schemes, including double and tripple buffering.

Signed-off-by: Joshua Henderson <[email protected]>
  • Loading branch information
joshua-henderson committed May 30, 2019
1 parent 96a3e46 commit f64a2d5
Show file tree
Hide file tree
Showing 3 changed files with 165 additions and 57 deletions.
53 changes: 47 additions & 6 deletions include/planes/plane.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,19 @@ struct kms_device;
*/
struct plane_data
{
/** The type of plane. */
int type;
/** Optional human name for the plane. */
char name[255];
/** Pointer to the underlying KMS plane object. */
struct kms_plane* plane;
/** Pointer to the underlying KMS framebuffer object. */
struct kms_framebuffer* fb;
struct kms_framebuffer** fbs;
/** The framebuffer. Must call plane_map() to allocate this. */
void* buf;
void** bufs;
unsigned int front_buf;
/** The number of framebuffers. */
uint32_t buffer_count;
/** Plane type index, starting at zero. */
unsigned int index;
/** X coordinate of the plane. */
Expand All @@ -72,7 +77,7 @@ struct plane_data
/** Scale of the plane. 1.0 is no scale. */
double scale;
/** GEM name of the plane. */
uint32_t gem_name;
uint32_t* gem_names;
/** Alpha value of the plane. 0 to 255. */
uint32_t alpha;
uint32_t alpha_applied;
Expand Down Expand Up @@ -133,7 +138,8 @@ struct plane_data
* Create a plane.
*
* @param device The already created KMS device.
* @param type The type of plane: DRM_PLANE_TYPE_PRIMARY,DRM_PLANE_TYPE_OVERLAY
* @param type The type of plane: DRM_PLANE_TYPE_PRIMARY,DRM_PLANE_TYPE_OVERLAY,
* DRM_PLANE_TYPE_CURSOR
* @param index The index of the plane.
* @param width The width in pixels of the plane.
* @param height The height in pixels of the plane.
Expand All @@ -143,7 +149,26 @@ struct plane_data* plane_create(struct kms_device* device, int type, int index,
int width, int height, uint32_t format);

/**
* Free a plane allocated with plane_create().
* Create a plane with one of more framebuffers.
*
* When more than one framebuffer is allocated, plane_flip() can be used to
* iterate through them on the plane.
*
* @param device The already created KMS device.
* @param type The type of plane: DRM_PLANE_TYPE_PRIMARY,DRM_PLANE_TYPE_OVERLAY,
* DRM_PLANE_TYPE_CURSOR
* @param index The index of the plane.
* @param width The width in pixels of the plane.
* @param height The height in pixels of the plane.
* @param format A DRM format, or zero to automatically choose.
* @param buffer_count The number of buffers to allocate.
*/
struct plane_data* plane_create_buffered(struct kms_device* device, int type,
int index, int width, int height,
uint32_t format, uint32_t buffer_count);

/**
* Free a plane allocated with plane_create() or plane_create_buffered().
*
* @param plane The plane.
*/
Expand Down Expand Up @@ -305,7 +330,7 @@ void plane_set_pan_size(struct plane_data* plane, int width, int height);
* Map the framebuffer.
*
* This is not done by default because the process that calls plane_create()
* isn't necessarily the one using the framebuffer.
* or plane_create_buffered() isn't necessarily the one using the framebuffer.
*
* @param plane The plane.
*/
Expand All @@ -328,6 +353,22 @@ void plane_fb_unmap(struct plane_data* plane);
int plane_fb_reallocate(struct plane_data* plane,
int width, int height, uint32_t format);

/**
* Perform a flip to the target buffer index as the front buffer.
*
* When you allocate a plane, you can specify how many buffers to create for the
* plane. This is usually going to be 1, 2, or 3.
*
* When you allocate more than 1 buffer, you can then start to refresh the
* screen timed to vertical syncs of the display. This will prevent side effects
* such as tearing. This is typically called double or tripple buffering based
* on 2 or 3 buffers, respectively.
*
* @param plane The plane.
* @param target The framebuffer index to switch to.
*/
int plane_flip(struct plane_data* plane, uint32_t target);

#ifdef __cplusplus
}
#endif
Expand Down
42 changes: 21 additions & 21 deletions src/engine.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,21 +43,21 @@ static void configure_plane(struct plane_data* plane, uint32_t colors[2],
int x;

if (mesh)
render_fb_mesh_pattern(plane->fb);
render_fb_mesh_pattern(plane->fbs[0]);
else if (vgradient)
render_fb_vgradient(plane->fb, colors[0], colors[1]);
render_fb_vgradient(plane->fbs[0], colors[0], colors[1]);
else
render_fb_checker_pattern(plane->fb, colors[0], colors[1]);
render_fb_checker_pattern(plane->fbs[0], colors[0], colors[1]);

if (filename)
render_fb_image(plane->fb, filename);
render_fb_image(plane->fbs[0], filename);

if (filename_raw)
render_fb_image_raw(plane->fb, filename_raw);
render_fb_image_raw(plane->fbs[0], filename_raw);

for (x = 0; x < 255;x++)
if (strlen(plane->text[x].str))
render_fb_text(plane->fb, plane->text[x].x, plane->text[x].y,
render_fb_text(plane->fbs[0], plane->text[x].x, plane->text[x].y,
plane->text[x].str, plane->text[x].color,
plane->text[x].size);
}
Expand Down Expand Up @@ -753,9 +753,9 @@ void engine_run_once(struct kms_device* device, struct plane_data** planes,
bool trigger = false;
bool move = false;

if (!planes[i] || !planes[i]->plane || !planes[i]->fb ||
(planes[i]->plane->type != DRM_PLANE_TYPE_OVERLAY &&
planes[i]->plane->type != DRM_PLANE_TYPE_CURSOR))
if (!planes[i] || !planes[i]->plane || !planes[i]->fbs[0] ||
(planes[i]->plane->type != DRM_PLANE_TYPE_OVERLAY &&
planes[i]->plane->type != DRM_PLANE_TYPE_CURSOR))
continue;

if (planes[i]->move_flags & MOVE_X_WARP) {
Expand All @@ -773,7 +773,7 @@ void engine_run_once(struct kms_device* device, struct plane_data** planes,
} else {
if ((planes[i]->x + plane_width(planes[i]) >
device->screens[0]->width + plane_width(planes[i]))) {
planes[i]->x = planes[i]->fb->width * -1;
planes[i]->x = planes[i]->fbs[0]->width * -1;
trigger = true;
}
}
Expand Down Expand Up @@ -828,17 +828,17 @@ void engine_run_once(struct kms_device* device, struct plane_data** planes,
}

if (planes[i]->move_flags & MOVE_Y_WARP) {
if ((planes[i]->y + planes[i]->fb->height >
device->screens[0]->height + planes[i]->fb->height + planes[i]->fb->height)) {
planes[i]->y = planes[i]->fb->height * -1;
if ((planes[i]->y + planes[i]->fbs[0]->height >
device->screens[0]->height + planes[i]->fbs[0]->height + planes[i]->fbs[0]->height)) {
planes[i]->y = planes[i]->fbs[0]->height * -1;
trigger = true;
}
planes[i]->y += planes[i]->move.yspeed;
move = true;
}

if (planes[i]->move_flags & MOVE_Y_BOUNCE) {
if (planes[i]->y + planes[i]->fb->height > device->screens[0]->height ||
if (planes[i]->y + planes[i]->fbs[0]->height > device->screens[0]->height ||
planes[i]->y < 0) {
planes[i]->move.yspeed *= -1;
trigger = true;
Expand All @@ -859,7 +859,7 @@ void engine_run_once(struct kms_device* device, struct plane_data** planes,

if (planes[i]->move_flags & MOVE_Y_BOUNCE_OUT) {
if ((planes[i]->y+planes[i]->move.yspeed > (int)device->screens[0]->height) ||
(planes[i]->y+planes[i]->move.yspeed < ((int)planes[i]->fb->height * -1))) {
(planes[i]->y+planes[i]->move.yspeed < ((int)planes[i]->fbs[0]->height * -1))) {
planes[i]->move.yspeed *= -1;
trigger = true;
}
Expand Down Expand Up @@ -940,13 +940,13 @@ void engine_run_once(struct kms_device* device, struct plane_data** planes,
planes[i]->pan.y = planes[i]->sprite.y;

// support sheets that have frames on multiple rows
if (planes[i]->pan.x + planes[i]->sprite.width >= (int)planes[i]->fb->width) {
if (planes[i]->pan.x + planes[i]->sprite.width >= (int)planes[i]->fbs[0]->width) {
int x = planes[i]->sprite.x + (planes[i]->sprite.index * planes[i]->sprite.width);

planes[i]->pan.x = (x % planes[i]->fb->width);
planes[i]->pan.y = ((x / planes[i]->fb->width) * planes[i]->sprite.y) +
planes[i]->pan.x = (x % planes[i]->fbs[0]->width);
planes[i]->pan.y = ((x / planes[i]->fbs[0]->width) * planes[i]->sprite.y) +

(x / planes[i]->fb->width) * planes[i]->sprite.height;
(x / planes[i]->fbs[0]->width) * planes[i]->sprite.height;
}

planes[i]->pan.width = planes[i]->sprite.width;
Expand All @@ -957,10 +957,10 @@ void engine_run_once(struct kms_device* device, struct plane_data** planes,

if (trigger) {
if (planes[i]->transform_flags & TRANSFORM_FLIP_HORIZONTAL) {
flip_fb_horizontal(planes[i]->fb);
flip_fb_horizontal(planes[i]->fbs[0]);
}
if (planes[i]->transform_flags & TRANSFORM_FLIP_VERTICAL) {
flip_fb_vertical(planes[i]->fb);
flip_fb_vertical(planes[i]->fbs[0]);
}

if (planes[i]->transform_flags & TRANSFORM_ROTATE_CLOCKWISE) {
Expand Down
Loading

0 comments on commit f64a2d5

Please sign in to comment.