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
254
255
256
257
258
259
260
261
262
263
264
265
266
267
|
/*
* Copyright (c) 2016 Intel Corporation
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that copyright
* notice and this permission notice appear in supporting documentation, and
* that the name of the copyright holders not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. The copyright holders make no representations
* about the suitability of this software for any purpose. It is provided "as
* is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE.
*/
#ifndef __DRM_FRAMEBUFFER_H__
#define __DRM_FRAMEBUFFER_H__
#include <linux/list.h>
#include <linux/ctype.h>
#include <drm/drm_mode_object.h>
struct drm_framebuffer;
struct drm_file;
struct drm_device;
/**
* struct drm_framebuffer_funcs - framebuffer hooks
*/
struct drm_framebuffer_funcs {
/**
* @destroy:
*
* Clean up framebuffer resources, specifically also unreference the
* backing storage. The core guarantees to call this function for every
* framebuffer successfully created by ->fb_create() in
* &drm_mode_config_funcs. Drivers must also call
* drm_framebuffer_cleanup() to release DRM core resources for this
* framebuffer.
*/
void (*destroy)(struct drm_framebuffer *framebuffer);
/**
* @create_handle:
*
* Create a buffer handle in the driver-specific buffer manager (either
* GEM or TTM) valid for the passed-in struct &drm_file. This is used by
* the core to implement the GETFB IOCTL, which returns (for
* sufficiently priviledged user) also a native buffer handle. This can
* be used for seamless transitions between modesetting clients by
* copying the current screen contents to a private buffer and blending
* between that and the new contents.
*
* GEM based drivers should call drm_gem_handle_create() to create the
* handle.
*
* RETURNS:
*
* 0 on success or a negative error code on failure.
*/
int (*create_handle)(struct drm_framebuffer *fb,
struct drm_file *file_priv,
unsigned int *handle);
/**
* @dirty:
*
* Optional callback for the dirty fb IOCTL.
*
* Userspace can notify the driver via this callback that an area of the
* framebuffer has changed and should be flushed to the display
* hardware. This can also be used internally, e.g. by the fbdev
* emulation, though that's not the case currently.
*
* See documentation in drm_mode.h for the struct drm_mode_fb_dirty_cmd
* for more information as all the semantics and arguments have a one to
* one mapping on this function.
*
* RETURNS:
*
* 0 on success or a negative error code on failure.
*/
int (*dirty)(struct drm_framebuffer *framebuffer,
struct drm_file *file_priv, unsigned flags,
unsigned color, struct drm_clip_rect *clips,
unsigned num_clips);
};
/**
* struct drm_framebuffer - frame buffer object
*
* Note that the fb is refcounted for the benefit of driver internals,
* for example some hw, disabling a CRTC/plane is asynchronous, and
* scanout does not actually complete until the next vblank. So some
* cleanup (like releasing the reference(s) on the backing GEM bo(s))
* should be deferred. In cases like this, the driver would like to
* hold a ref to the fb even though it has already been removed from
* userspace perspective. See drm_framebuffer_reference() and
* drm_framebuffer_unreference().
*
* The refcount is stored inside the mode object @base.
*/
struct drm_framebuffer {
/**
* @dev: DRM device this framebuffer belongs to
*/
struct drm_device *dev;
/**
* @head: Place on the dev->mode_config.fb_list, access protected by
* dev->mode_config.fb_lock.
*/
struct list_head head;
/**
* @base: base modeset object structure, contains the reference count.
*/
struct drm_mode_object base;
/**
* @funcs: framebuffer vfunc table
*/
const struct drm_framebuffer_funcs *funcs;
/**
* @pitches: Line stride per buffer. For userspace created object this
* is copied from drm_mode_fb_cmd2.
*/
unsigned int pitches[4];
/**
* @offsets: Offset from buffer start to the actual pixel data in bytes,
* per buffer. For userspace created object this is copied from
* drm_mode_fb_cmd2.
*
* Note that this is a linear offset and does not take into account
* tiling or buffer laytou per @modifier. It meant to be used when the
* actual pixel data for this framebuffer plane starts at an offset,
* e.g. when multiple planes are allocated within the same backing
* storage buffer object. For tiled layouts this generally means it
* @offsets must at least be tile-size aligned, but hardware often has
* stricter requirements.
*
* This should not be used to specifiy x/y pixel offsets into the buffer
* data (even for linear buffers). Specifying an x/y pixel offset is
* instead done through the source rectangle in struct &drm_plane_state.
*/
unsigned int offsets[4];
/**
* @modifier: Data layout modifier. This is used to describe
* tiling, or also special layouts (like compression) of auxiliary
* buffers. For userspace created object this is copied from
* drm_mode_fb_cmd2.
*/
uint64_t modifier;
/**
* @width: Logical width of the visible area of the framebuffer, in
* pixels.
*/
unsigned int width;
/**
* @height: Logical height of the visible area of the framebuffer, in
* pixels.
*/
unsigned int height;
/**
* @depth: Depth in bits per pixel for RGB formats. 0 for everything
* else. Legacy information derived from @pixel_format, it's suggested to use
* the DRM FOURCC codes and helper functions directly instead.
*/
unsigned int depth;
/**
* @bits_per_pixel: Storage used bits per pixel for RGB formats. 0 for
* everything else. Legacy information derived from @pixel_format, it's
* suggested to use the DRM FOURCC codes and helper functions directly
* instead.
*/
int bits_per_pixel;
/**
* @flags: Framebuffer flags like DRM_MODE_FB_INTERLACED or
* DRM_MODE_FB_MODIFIERS.
*/
int flags;
/**
* @pixel_format: DRM FOURCC code describing the pixel format.
*/
uint32_t pixel_format; /* fourcc format */
/**
* @hot_x: X coordinate of the cursor hotspot. Used by the legacy cursor
* IOCTL when the driver supports cursor through a DRM_PLANE_TYPE_CURSOR
* universal plane.
*/
int hot_x;
/**
* @hot_y: Y coordinate of the cursor hotspot. Used by the legacy cursor
* IOCTL when the driver supports cursor through a DRM_PLANE_TYPE_CURSOR
* universal plane.
*/
int hot_y;
/**
* @filp_head: Placed on struct &drm_file fbs list_head, protected by
* fbs_lock in the same structure.
*/
struct list_head filp_head;
};
#define obj_to_fb(x) container_of(x, struct drm_framebuffer, base)
int drm_framebuffer_init(struct drm_device *dev,
struct drm_framebuffer *fb,
const struct drm_framebuffer_funcs *funcs);
struct drm_framebuffer *drm_framebuffer_lookup(struct drm_device *dev,
uint32_t id);
void drm_framebuffer_remove(struct drm_framebuffer *fb);
void drm_framebuffer_cleanup(struct drm_framebuffer *fb);
void drm_framebuffer_unregister_private(struct drm_framebuffer *fb);
/**
* drm_framebuffer_reference - incr the fb refcnt
* @fb: framebuffer
*
* This functions increments the fb's refcount.
*/
static inline void drm_framebuffer_reference(struct drm_framebuffer *fb)
{
drm_mode_object_reference(&fb->base);
}
/**
* drm_framebuffer_unreference - unref a framebuffer
* @fb: framebuffer to unref
*
* This functions decrements the fb's refcount and frees it if it drops to zero.
*/
static inline void drm_framebuffer_unreference(struct drm_framebuffer *fb)
{
drm_mode_object_unreference(&fb->base);
}
/**
* drm_framebuffer_read_refcount - read the framebuffer reference count.
* @fb: framebuffer
*
* This functions returns the framebuffer's reference count.
*/
static inline uint32_t drm_framebuffer_read_refcount(struct drm_framebuffer *fb)
{
return atomic_read(&fb->base.refcount.refcount);
}
/**
* drm_for_each_fb - iterate over all framebuffers
* @fb: the loop cursor
* @dev: the DRM device
*
* Iterate over all framebuffers of @dev. User must hold the fb_lock from
* &drm_mode_config.
*/
#define drm_for_each_fb(fb, dev) \
for (WARN_ON(!mutex_is_locked(&(dev)->mode_config.fb_lock)), \
fb = list_first_entry(&(dev)->mode_config.fb_list, \
struct drm_framebuffer, head); \
&fb->head != (&(dev)->mode_config.fb_list); \
fb = list_next_entry(fb, head))
#endif
|