File: scaled-buffer.h

package info (click to toggle)
labwc 0.9.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 2,980 kB
  • sloc: ansic: 34,416; perl: 5,836; xml: 875; sh: 162; python: 131; makefile: 12
file content (146 lines) | stat: -rw-r--r-- 6,129 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef LABWC_SCALED_BUFFER_H
#define LABWC_SCALED_BUFFER_H

#include <wayland-server-core.h>

#define LAB_SCALED_BUFFER_MAX_CACHE 2

struct wlr_buffer;
struct wlr_scene_tree;
struct lab_data_buffer;
struct scaled_buffer;

struct scaled_buffer_impl {
	/* Return a new buffer optimized for the new scale */
	struct lab_data_buffer *(*create_buffer)
		(struct scaled_buffer *scaled_buffer, double scale);
	/* Might be NULL or used for cleaning up */
	void (*destroy)(struct scaled_buffer *scaled_buffer);
	/* Returns true if the two buffers are visually the same */
	bool (*equal)(struct scaled_buffer *scaled_buffer_a,
		struct scaled_buffer *scaled_buffer_b);
};

struct scaled_buffer {
	struct wlr_scene_buffer *scene_buffer;
	int width;   /* unscaled, read only */
	int height;  /* unscaled, read only */
	void *data;  /* opaque user data */

	/* Private */
	bool drop_buffer;
	double active_scale;
	/* cached wlr_buffers for each scale */
	struct wl_list cache;  /* struct scaled_buffer_cache_entry.link */
	struct wl_listener destroy;
	struct wl_listener outputs_update;
	const struct scaled_buffer_impl *impl;
	struct wl_list link; /* all_scaled_buffers */
};

/*
 *                                  |                 |
 *                        .------------------.  .------------.
 *       scaled_buffer    | new_output_scale |  | set_buffer |
 *       architecture     ´------------------`  ´------------`
 *                                  |                ^
 *    .-----------------------------|----------------|-----------.
 *    |                             v                |           |
 *    |  .---------------.    .-------------------------.        |
 *    |  | scaled_buffer |----| wlr_buffer LRU cache(2) |<---,   |
 *    |  ´---------------`    ´-------------------------`    |   |
 *    |           |                       |                  |   |
 *    |        .------.       .--------------------------.   |   |
 *    |        | impl |       | wlr_buffer LRU cache of  |   |   |
 *    |        ´------`       |   other scaled_buffers   |   |   |
 *    |                       |   with impl->equal()     |   |   |
 *    |                       ´--------------------------`   |   |
 *    |                          /              |            |   |
 *    |                   not found           found          |   |
 *    |     .-----------------------.     .-----------.      |   |
 *    |     | impl->create_buffer() |--->| wlr_buffer |------`   |
 *    |     ´-----------------------`    ´------------`          |
 *    |                                                          |
 *    ´----------------------------------------------------------`
 */

/**
 * Create an auto scaling buffer that creates a wlr_scene_buffer
 * and subscribes to its output_enter and output_leave signals.
 *
 * If the maximal scale changes, it either sets an already existing buffer
 * that was rendered for the current scale or - if there is none - calls
 * implementation->create_buffer(self, scale) to get a new lab_data_buffer
 * optimized for the new scale.
 *
 * Up to LAB_SCALED_BUFFER_MAX_CACHE (2) buffers are cached in an LRU fashion
 * to handle the majority of use cases where a view is moved between no more
 * than two different scales.
 *
 * scaled_buffer will clean up automatically once the internal
 * wlr_scene_buffer is being destroyed. If implementation->destroy is set
 * it will also get called so a consumer of this API may clean up its own
 * allocations.
 *
 * Besides caching buffers for each scale per scaled_buffer, we also
 * store all the scaled_buffers from all the implementers in a list
 * in order to reuse backing buffers for visually duplicated
 * scaled_buffers found via impl->equal().
 *
 * All requested lab_data_buffers via impl->create_buffer() will be locked
 * during the lifetime of the buffer in the internal cache and unlocked
 * when being evacuated from the cache (due to LAB_SCALED_BUFFER_MAX_CACHE
 * or the internal wlr_scene_buffer being destroyed).
 *
 * If drop_buffer was set during creation of the scaled_buffer, the
 * backing wlr_buffer behind a lab_data_buffer will also get dropped
 * (via wlr_buffer_drop). If there are no more locks (consumers) of the
 * respective buffer this will then cause the lab_data_buffer to be free'd.
 *
 * In the case of the buffer provider dropping the buffer itself (due to
 * for example a Reconfigure event) the lock prevents the buffer from being
 * destroyed until the buffer is evacuated from the internal cache and thus
 * unlocked.
 *
 * This allows using scaled_buffer for an autoscaling font_buffer
 * (which gets free'd automatically) and also for theme components like
 * rounded corner images or button icons whose buffers only exist once but
 * are references by multiple windows with their own scaled_buffers.
 *
 * The rough idea is: use drop_buffer = true for one-shot buffers and false
 * for buffers that should outlive the scaled_buffer instance itself.
 */
struct scaled_buffer *scaled_buffer_create(
	struct wlr_scene_tree *parent,
	const struct scaled_buffer_impl *implementation,
	bool drop_buffer);

/**
 * scaled_buffer_request_update - mark the buffer that needs to be
 * updated
 * @width: the width of the buffer to be rendered, in scene coordinates
 * @height: the height of the buffer to be rendered, in scene coordinates
 *
 * This function should be called when the states bound to the buffer are
 * updated and ready for rendering.
 */
void scaled_buffer_request_update(struct scaled_buffer *self,
	int width, int height);

/**
 * scaled_buffer_invalidate_sharing - clear the list of entire cached
 * scaled_buffers used to share visually dupliated buffers. This should
 * be called on Reconfigure to force updates of newly created
 * scaled_buffers rather than reusing ones created before Reconfigure.
 */
void scaled_buffer_invalidate_sharing(void);

/* Private */
struct scaled_buffer_cache_entry {
	struct wl_list link;   /* struct scaled_buffer.cache */
	struct wlr_buffer *buffer;
	double scale;
};

#endif /* LABWC_SCALED_BUFFER_H */