1 /*
2 * Copyright © 2013 Keith Packard
3 * Copyright © 2015 Boyan Ding
4 *
5 * Permission to use, copy, modify, distribute, and sell this software and its
6 * documentation for any purpose is hereby granted without fee, provided that
7 * the above copyright notice appear in all copies and that both that copyright
8 * notice and this permission notice appear in supporting documentation, and
9 * that the name of the copyright holders not be used in advertising or
10 * publicity pertaining to distribution of the software without specific,
11 * written prior permission. The copyright holders make no representations
12 * about the suitability of this software for any purpose. It is provided "as
13 * is" without express or implied warranty.
14 *
15 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
21 * OF THIS SOFTWARE.
22 */
23
24 #ifndef LOADER_DRI3_HEADER_H
25 #define LOADER_DRI3_HEADER_H
26
27 #include <stdbool.h>
28 #include <stdint.h>
29
30 #include <xcb/xcb.h>
31 #include <xcb/dri3.h>
32 #include <xcb/present.h>
33
34 #include <GL/gl.h>
35 #include "mesa_interface.h"
36 #include "util/macros.h"
37 #include <c11/threads.h>
38
39 enum loader_dri3_buffer_type {
40 loader_dri3_buffer_back = 0,
41 loader_dri3_buffer_front = 1
42 };
43
44 struct loader_dri3_buffer {
45 __DRIimage *image;
46 uint32_t pixmap;
47
48 /* default case: linear buffer allocated in render gpu vram.
49 * p2p case: linear buffer allocated in display gpu vram and imported
50 * to render gpu. p2p case is enabled when driver name matches
51 * while creating screen in dri3_create_screen() function.
52 */
53 __DRIimage *linear_buffer;
54
55 /* Synchronization between the client and X server is done using an
56 * xshmfence that is mapped into an X server SyncFence. This lets the
57 * client check whether the X server is done using a buffer with a simple
58 * xshmfence call, rather than going to read X events from the wire.
59 *
60 * However, we can only wait for one xshmfence to be triggered at a time,
61 * so we need to know *which* buffer is going to be idle next. We do that
62 * by waiting for a PresentIdleNotify event. When that event arrives, the
63 * 'busy' flag gets cleared and the client knows that the fence has been
64 * triggered, and that the wait call will not block.
65 */
66
67 uint32_t sync_fence; /* XID of X SyncFence object */
68 struct xshmfence *shm_fence; /* pointer to xshmfence object */
69 bool busy; /* Set on swap, cleared on IdleNotify */
70 bool own_pixmap; /* We allocated the pixmap ID, free on destroy */
71 bool reallocate; /* Buffer should be reallocated and not reused */
72
73 uint32_t num_planes;
74 uint32_t size;
75 int strides[4];
76 int offsets[4];
77 uint64_t modifier;
78 uint32_t cpp;
79 uint32_t flags;
80 uint32_t width, height;
81 uint64_t last_swap;
82 };
83
84
85 #define LOADER_DRI3_MAX_BACK 4
86 #define LOADER_DRI3_BACK_ID(i) (i)
87 #define LOADER_DRI3_FRONT_ID (LOADER_DRI3_MAX_BACK)
88
89 static inline int
loader_dri3_pixmap_buf_id(enum loader_dri3_buffer_type buffer_type)90 loader_dri3_pixmap_buf_id(enum loader_dri3_buffer_type buffer_type)
91 {
92 if (buffer_type == loader_dri3_buffer_back)
93 return LOADER_DRI3_BACK_ID(0);
94 else
95 return LOADER_DRI3_FRONT_ID;
96 }
97
98 struct loader_dri3_drawable;
99
100 struct loader_dri3_vtable {
101 void (*set_drawable_size)(struct loader_dri3_drawable *, int, int);
102 bool (*in_current_context)(struct loader_dri3_drawable *);
103 __DRIcontext *(*get_dri_context)(struct loader_dri3_drawable *);
104 __DRIscreen *(*get_dri_screen)(void);
105 void (*flush_drawable)(struct loader_dri3_drawable *, unsigned);
106 };
107
108 #define LOADER_DRI3_NUM_BUFFERS (1 + LOADER_DRI3_MAX_BACK)
109
110 enum loader_dri3_drawable_type {
111 LOADER_DRI3_DRAWABLE_UNKNOWN,
112 LOADER_DRI3_DRAWABLE_WINDOW,
113 LOADER_DRI3_DRAWABLE_PIXMAP,
114 LOADER_DRI3_DRAWABLE_PBUFFER,
115 };
116
117 struct loader_dri3_drawable {
118 xcb_connection_t *conn;
119 xcb_screen_t *screen;
120 __DRIdrawable *dri_drawable;
121 xcb_drawable_t drawable;
122 xcb_window_t window;
123 xcb_xfixes_region_t region;
124 int width;
125 int height;
126 int depth;
127 uint8_t have_back;
128 uint8_t have_fake_front;
129 enum loader_dri3_drawable_type type;
130
131 /* Information about the GPU owning the buffer */
132 bool multiplanes_available;
133 bool prefer_back_buffer_reuse;
134 __DRIscreen *dri_screen_render_gpu;
135 /* dri_screen_display_gpu holds display GPU in case of prime gpu offloading else
136 * dri_screen_render_gpu and dri_screen_display_gpu is same.
137 * In case of prime gpu offloading, if display and render driver names are different
138 * (potentially not compatible), dri_screen_display_gpu will be NULL but fd_display_gpu
139 * will still hold fd for display driver.
140 */
141 __DRIscreen *dri_screen_display_gpu;
142
143 /* SBC numbers are tracked by using the serial numbers
144 * in the present request and complete events
145 */
146 uint64_t send_sbc;
147 uint64_t recv_sbc;
148
149 /* Last received UST/MSC values for pixmap present complete */
150 uint64_t ust, msc;
151
152 /* Last received UST/MSC values from present notify msc event */
153 uint64_t notify_ust, notify_msc;
154
155 struct loader_dri3_buffer *buffers[LOADER_DRI3_NUM_BUFFERS];
156 int cur_back;
157 int cur_num_back;
158 int max_num_back;
159 int cur_blit_source;
160
161 uint32_t *stamp;
162
163 xcb_present_event_t eid;
164 xcb_gcontext_t gc;
165 xcb_special_event_t *special_event;
166
167 bool first_init;
168 bool adaptive_sync;
169 bool adaptive_sync_active;
170 bool block_on_depleted_buffers;
171 bool queries_buffer_age;
172 int swap_interval;
173
174 const struct loader_dri3_vtable *vtable;
175
176 unsigned int back_format;
177 xcb_present_complete_mode_t last_present_mode;
178
179 bool is_protected_content;
180
181 /* Currently protects the following fields:
182 * event_cnd, has_event_waiter,
183 * recv_sbc, ust, msc, recv_msc_serial,
184 * notify_ust, notify_msc
185 */
186 mtx_t mtx;
187 cnd_t event_cnd;
188 unsigned last_special_event_sequence;
189 bool has_event_waiter;
190 };
191
192 PUBLIC void
193 loader_dri3_set_swap_interval(struct loader_dri3_drawable *draw,
194 int interval);
195
196 PUBLIC void
197 loader_dri3_drawable_fini(struct loader_dri3_drawable *draw);
198
199 PUBLIC int
200 loader_dri3_drawable_init(xcb_connection_t *conn,
201 xcb_drawable_t drawable,
202 enum loader_dri3_drawable_type type,
203 __DRIscreen *dri_screen_render_gpu,
204 __DRIscreen *dri_screen_display_gpu,
205 bool is_multiplanes_available,
206 bool prefer_back_buffer_reuse,
207 const __DRIconfig *dri_config,
208 const struct loader_dri3_vtable *vtable,
209 struct loader_dri3_drawable*);
210
211 PUBLIC bool loader_dri3_wait_for_msc(struct loader_dri3_drawable *draw,
212 int64_t target_msc,
213 int64_t divisor, int64_t remainder,
214 int64_t *ust, int64_t *msc, int64_t *sbc);
215
216 PUBLIC int64_t
217 loader_dri3_swap_buffers_msc(struct loader_dri3_drawable *draw,
218 int64_t target_msc, int64_t divisor,
219 int64_t remainder, unsigned flush_flags,
220 const int *rects, int n_rects,
221 bool force_copy);
222
223 PUBLIC int
224 loader_dri3_wait_for_sbc(struct loader_dri3_drawable *draw,
225 int64_t target_sbc, int64_t *ust,
226 int64_t *msc, int64_t *sbc);
227
228 PUBLIC int loader_dri3_query_buffer_age(struct loader_dri3_drawable *draw);
229
230 PUBLIC void
231 loader_dri3_flush(struct loader_dri3_drawable *draw,
232 unsigned flags,
233 enum __DRI2throttleReason throttle_reason);
234
235 PUBLIC void
236 loader_dri3_copy_sub_buffer(struct loader_dri3_drawable *draw,
237 int x, int y,
238 int width, int height,
239 bool flush);
240
241 PUBLIC void
242 loader_dri3_copy_drawable(struct loader_dri3_drawable *draw,
243 xcb_drawable_t dest,
244 xcb_drawable_t src);
245
246 PUBLIC void
247 loader_dri3_wait_x(struct loader_dri3_drawable *draw);
248
249 PUBLIC void
250 loader_dri3_wait_gl(struct loader_dri3_drawable *draw);
251
252 PUBLIC __DRIimage *
253 loader_dri3_create_image(xcb_connection_t *c,
254 xcb_dri3_buffer_from_pixmap_reply_t *bp_reply,
255 unsigned int fourcc,
256 __DRIscreen *dri_screen,
257 void *loaderPrivate);
258
259 #ifdef HAVE_X11_DRM
260 PUBLIC __DRIimage *
261 loader_dri3_create_image_from_buffers(xcb_connection_t *c,
262 xcb_dri3_buffers_from_pixmap_reply_t *bp_reply,
263 unsigned int fourcc,
264 __DRIscreen *dri_screen,
265 void *loaderPrivate);
266 #endif
267 PUBLIC int
268 loader_dri3_get_buffers(__DRIdrawable *driDrawable,
269 unsigned int format,
270 uint32_t *stamp,
271 void *loaderPrivate,
272 uint32_t buffer_mask,
273 struct __DRIimageList *buffers);
274
275 PUBLIC void
276 loader_dri3_update_drawable_geometry(struct loader_dri3_drawable *draw);
277
278 PUBLIC void
279 loader_dri3_swapbuffer_barrier(struct loader_dri3_drawable *draw);
280
281 PUBLIC void
282 loader_dri3_close_screen(__DRIscreen *dri_screen);
283 __DRIimage *
284 loader_dri3_get_pixmap_buffer(xcb_connection_t *conn, xcb_drawable_t pixmap, __DRIscreen *screen,
285 unsigned fourcc, bool multiplanes_available,
286 int *width, int *height, void *loader_data);
287 #endif
288