-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwsialloc.h
253 lines (229 loc) · 11.3 KB
/
wsialloc.h
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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
/*
* Copyright (c) 2017-2024 Arm Limited.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/**
* @file
* Window System Integration (WSI) Buffer Allocation Interface
*/
#ifndef _WSIALLOC_H_
#define _WSIALLOC_H_
#include <stdint.h>
#include <stdbool.h>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
#include <drm_fourcc.h>
#pragma GCC diagnostic pop
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/**
* @page wsialloc_page Window System Integration (WSI) Buffer Allocation
*
* wsialloc is a standalone module for doing window system/platform agnostic multi-plane buffer allocation.
*
* The underlying implementation will allocate sufficient space for the desired buffer format in a way that is
* compatible with the window system and the GPU (e.g. accounting for buffer row-start alignment requirements).
*
* @note The bare minimum work is done to provide the buffer. For example, it is up to the client to initialize the data
* if that is required for the desired buffer format.
*
* The underlying allocator implementation is chosen at compile time.
*
* All API Public entry points are implemented in a way that is thread safe, and the client does not need to be
* concerned with locking when using these APIs. If implementers make use of non-threadsafe functions, writable global
* data etc they must make appropriate use of locks.
*
* Version History:
* 1 - Initial wsialloc interface
* 2 - Added WSIALLOC_ALLOCATE_HIGHEST_FIXED_RATE_COMPRESSION
* 3 - Grouped the return values of wsialloc_alloc to wsialloc_allocate_result and added another value for returning
* whether or not the allocation will be disjoint.
*/
#define WSIALLOC_INTERFACE_VERSION 3
#define WSIALLOC_CONCAT(x, y) x##y
#define WSIALLOC_SYMBOL_VERSION(symbol, version) WSIALLOC_CONCAT(symbol, version)
/**
* @brief This symbol must be defined by any implementation of the wsialloc interface as defined in this header.
*
* A wsialloc implementation defining this symbol is declaring it implements
* the exact version of the wsialloc interface defined in this header.
*/
#define WSIALLOC_IMPLEMENTATION_VERSION_SYMBOL \
WSIALLOC_SYMBOL_VERSION(wsialloc_symbol_version_, WSIALLOC_INTERFACE_VERSION)
extern const uint32_t WSIALLOC_IMPLEMENTATION_VERSION_SYMBOL;
/**
* @brief Aborts if the wsialloc implementation version is not the expected one.
*
* This macro calls abort() if the version of the wsialloc implementation that was linked to the code using this
* macro is not matching the version defined in the wsialloc.h header that is being included. This can be useful
* to catch compatibility issues in code that links to an external static library implementing the wsialloc
* interface.
*/
#define WSIALLOC_ASSERT_VERSION() \
if (WSIALLOC_IMPLEMENTATION_VERSION_SYMBOL != WSIALLOC_INTERFACE_VERSION) \
{ \
abort(); \
}
/* Maximum number of planes that can be returned */
#define WSIALLOC_MAX_PLANES 4
/**
* @brief Allocator type.
*
* Represents a private allocator structure.
*/
typedef struct wsialloc_allocator wsialloc_allocator;
typedef enum wsialloc_error
{
WSIALLOC_ERROR_NONE = 0,
WSIALLOC_ERROR_INVALID = -1,
WSIALLOC_ERROR_NOT_SUPPORTED = -2,
WSIALLOC_ERROR_NO_RESOURCE = -3,
} wsialloc_error;
/**
* @brief Allocate and initialize a new WSI Allocator from an existing file descriptor.
*
* The allocator from the function is used in subsequent calls to wsialloc_alloc() to allocate new buffers.
*
* @param[out] allocator a valid allocator for use in wsialloc functions.
*
* @retval WSIALLOC_ERROR_NONE on successful allocator creation.
* @retval WSIALLOC_ERROR_FAILED on failed allocator creation.
*/
wsialloc_error wsialloc_new(wsialloc_allocator **allocator);
/**
* @brief Close down and free resources associated with a WSI Allocator
*
* It is acceptable for buffer allocations from @p allocator to still exist and be in use. In this case, this function
* will return without waiting for the client to free the other allocations. However, the actual closing down and
* freeing of @p allocator will be deferred until the last allocation has been closed by the client.
*
* @note For the implementer: there is usually no need to track this explicitly, since kernel side allocators
* automatically defer their closing until all their allocations are also freed.
*
* @post no more new allocations should be made on @p allocator even if previous allocations still exist.
*
* @param allocator The allocator to close down and free.
*/
void wsialloc_delete(wsialloc_allocator *allocator);
enum wsialloc_format_flag
{
/** The format requires a memory allocation with the same file descriptor for all planes. */
WSIALLOC_FORMAT_NON_DISJOINT = 0x1,
};
enum wsialloc_allocate_flag
{
/** Allocates the buffer in protected memory. */
WSIALLOC_ALLOCATE_PROTECTED = 0x1,
/** Performs allocation calculations and format selection without allocating any memory. */
WSIALLOC_ALLOCATE_NO_MEMORY = 0x2,
/** Sets a preference for selecting the format with the highest fixed compression rate. */
WSIALLOC_ALLOCATE_HIGHEST_FIXED_RATE_COMPRESSION = 0x4,
};
typedef struct wsialloc_format
{
uint32_t fourcc; /**< The DRM_FORMAT_<...> code */
uint64_t modifier; /**< DRM modifier applied to all planes. */
uint64_t flags; /**< Set of @r wsialloc_format_flag format flags. */
} wsialloc_format;
typedef struct wsialloc_allocate_info
{
wsialloc_format *formats; /** List of formats to select from for the allocation. */
unsigned format_count; /** Number of elements in formats array. */
uint32_t width; /** The number of pixel columns required in the buffer. */
uint32_t height; /** The number of pixel rows required in the buffer. */
uint64_t flags; /** Set of @r wsialloc_allocate_flag allocation flags. */
} wsialloc_allocate_info;
typedef struct wsialloc_allocate_result
{
wsialloc_format format; /** The selected format for allocation. */
/** Per plane distance between rows of blocks divided by the block height measured in bytes. */
int average_row_strides[WSIALLOC_MAX_PLANES];
/** Per plane offset into the file descriptor for the start of the plane. */
uint32_t offsets[WSIALLOC_MAX_PLANES];
int buffer_fds[WSIALLOC_MAX_PLANES]; /** Per plane file descriptor for the buffer. */
bool is_disjoint; /** Whether different fds will be used for each plane. */
} wsialloc_allocate_result;
/**
* @brief Allocate a buffer from the WSI Allocator
*
* Allocate a buffer of size @p info::width x @p info::height in a way that is suitable for the underlying
* window system and GPU.
*
* The allocation is made using a format from the list specified in @p info::formats . On success, @p result::format is set with
* the selected format that was used for the allocation.
*
* Each plane is returned as a file descriptor. All other information returned about the buffer is also per-plane. It is
* assumed the caller already knows how many planes are implied by the @p result::format that was selected.
*
* Each row in the buffer may be larger than @p info::width to account for buffer alignment requirements in the
* underlying window system. @p result::average_row_strides must be examined to determine the number of bytes between
* subsequent rows in each of the buffer's planes. Only positive average_row_strides are allowed.
*
* The client may free the buffer's planes by invoking close() on some or all of the elements of @p result::buffer_fds
*
* The same file descriptor ('fd') may be written to different elements of @p result::buffer_fds more than once, for some or all
* of the planes. In this case:
* - @p result::offsets @b must be used to determine where each plane starts in the file descriptor
* - When the client frees the buffer, each unique fd in @p result::buffer_fds must only be closed once.
*
* Even if @p result::buffer_fds are all different or @p result::format is for a single plane, then the client must inspect
* @p result::offsets in case it contains non-zero values.
*
* If @p result::buffer_fds are different then @p result::disjoint should be set to true.
*
* @note The implementation might not export the file descriptors in @p result::buffer_fds in such a way that allows the client
* to directly map them on the CPU as writable (PROT_WRITE).
*
* The selected @p result::format modifier allows for a fourcc_mod_code() (as defined in drm_fourcc.h) to define
* a reordering or other modification of the data in the buffer's planes (e.g. compression,
* change in number of planes, etc).
*
* @p result::average_row_strides are per plane row average byte strides of the @p result::format. This is the number of bytes from the
* start of a row of blocks divided by the block height. It may also have format specific meaning for formats not in those
* categories.
*
* @p result::average_row_strides and @p result::offsets may have modifier-specific
* meaning when a @p result::format with modifier is selected.
*
* @pre @p result::average_row_strides, @p result::buffer_fds, @p result::offsets
* are pointers to storage large enough to hold per-plane information.
* @pre @p info::width >=1 && @p info::height >= 1
* @pre @p allocator is a currently valid WSI Allocator from wsialloc_new()
* @post The allocated buffer will be zeroed.
*
* @param allocator The WSI Allocator to allocate from.
* @param[in] info The requested allocation information.
* @param[out] result The allocation's result.
* @retval WSIALLOC_ERROR_NONE on successful buffer allocation.
* @retval WSIALLOC_ERROR_INVALID is returned for invalid parameters.
* @retval WSIALLOC_ERROR_NOT_SUPPORTED is returned for unsupported parameters, such as a modifier or recognized
* format not supported by the underlying window-system/allocator.
* @retval WSIALLOC_ERROR_NO_RESOURCE is returned on failed buffer allocation due to lack of available memory or other
* system resources.
*/
wsialloc_error wsialloc_alloc(wsialloc_allocator *allocator, const wsialloc_allocate_info *info,
wsialloc_allocate_result *result);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* _WSIALLOC_H_ */