loader: Add dri3 helper
[mesa.git] / src / loader / loader_dri3_helper.h
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/present.h>
32
33 #include <GL/gl.h>
34 #include <GL/internal/dri_interface.h>
35
36 enum loader_dri3_buffer_type {
37 loader_dri3_buffer_back = 0,
38 loader_dri3_buffer_front = 1
39 };
40
41 struct loader_dri3_buffer {
42 __DRIimage *image;
43 __DRIimage *linear_buffer;
44 uint32_t pixmap;
45
46 /* Synchronization between the client and X server is done using an
47 * xshmfence that is mapped into an X server SyncFence. This lets the
48 * client check whether the X server is done using a buffer with a simple
49 * xshmfence call, rather than going to read X events from the wire.
50 *
51 * However, we can only wait for one xshmfence to be triggered at a time,
52 * so we need to know *which* buffer is going to be idle next. We do that
53 * by waiting for a PresentIdleNotify event. When that event arrives, the
54 * 'busy' flag gets cleared and the client knows that the fence has been
55 * triggered, and that the wait call will not block.
56 */
57
58 uint32_t sync_fence; /* XID of X SyncFence object */
59 struct xshmfence *shm_fence; /* pointer to xshmfence object */
60 bool busy; /* Set on swap, cleared on IdleNotify */
61 bool own_pixmap; /* We allocated the pixmap ID, free on destroy */
62
63 uint32_t size;
64 uint32_t pitch;
65 uint32_t cpp;
66 uint32_t flags;
67 uint32_t width, height;
68 uint64_t last_swap;
69
70 enum loader_dri3_buffer_type buffer_type;
71 };
72
73
74 #define LOADER_DRI3_MAX_BACK 4
75 #define LOADER_DRI3_BACK_ID(i) (i)
76 #define LOADER_DRI3_FRONT_ID (LOADER_DRI3_MAX_BACK)
77
78 static inline int
79 loader_dri3_pixmap_buf_id(enum loader_dri3_buffer_type buffer_type)
80 {
81 if (buffer_type == loader_dri3_buffer_back)
82 return LOADER_DRI3_BACK_ID(0);
83 else
84 return LOADER_DRI3_FRONT_ID;
85 }
86
87 struct loader_dri3_extensions {
88 const __DRIcoreExtension *core;
89 const __DRIimageDriverExtension *image_driver;
90 const __DRI2flushExtension *flush;
91 const __DRI2configQueryExtension *config;
92 const __DRItexBufferExtension *tex_buffer;
93 const __DRIimageExtension *image;
94 };
95
96 struct loader_dri3_drawable;
97
98 struct loader_dri3_vtable {
99 int (*get_swap_interval)(struct loader_dri3_drawable *);
100 int (*clamp_swap_interval)(struct loader_dri3_drawable *, int);
101 void (*set_swap_interval)(struct loader_dri3_drawable *, int);
102 void (*set_drawable_size)(struct loader_dri3_drawable *, int, int);
103 bool (*in_current_context)(struct loader_dri3_drawable *);
104 __DRIcontext *(*get_dri_context)(struct loader_dri3_drawable *);
105 void (*flush_drawable)(struct loader_dri3_drawable *, unsigned);
106 void (*show_fps)(struct loader_dri3_drawable *, uint64_t);
107 };
108
109 #define LOADER_DRI3_NUM_BUFFERS (1 + LOADER_DRI3_MAX_BACK)
110
111 struct loader_dri3_drawable {
112 xcb_connection_t *conn;
113 __DRIdrawable *dri_drawable;
114 xcb_drawable_t drawable;
115 int width;
116 int height;
117 int depth;
118 uint8_t have_back;
119 uint8_t have_fake_front;
120 uint8_t is_pixmap;
121 uint8_t flipping;
122
123 /* Information about the GPU owning the buffer */
124 __DRIscreen *dri_screen;
125 bool is_different_gpu;
126
127 /* Present extension capabilities
128 */
129 uint32_t present_capabilities;
130
131 /* SBC numbers are tracked by using the serial numbers
132 * in the present request and complete events
133 */
134 uint64_t send_sbc;
135 uint64_t recv_sbc;
136
137 /* Last received UST/MSC values for pixmap present complete */
138 uint64_t ust, msc;
139
140 /* Last received UST/MSC values from present notify msc event */
141 uint64_t notify_ust, notify_msc;
142
143 /* Serial numbers for tracking wait_for_msc events */
144 uint32_t send_msc_serial;
145 uint32_t recv_msc_serial;
146
147 struct loader_dri3_buffer *buffers[LOADER_DRI3_NUM_BUFFERS];
148 int cur_back;
149 int num_back;
150
151 uint32_t *stamp;
152
153 xcb_present_event_t eid;
154 xcb_gcontext_t gc;
155 xcb_special_event_t *special_event;
156
157 bool first_init;
158
159 struct loader_dri3_extensions *ext;
160 struct loader_dri3_vtable *vtable;
161 };
162
163 void
164 loader_dri3_set_swap_interval(struct loader_dri3_drawable *draw,
165 int interval);
166
167 void
168 loader_dri3_drawable_fini(struct loader_dri3_drawable *draw);
169
170 int
171 loader_dri3_drawable_init(xcb_connection_t *conn,
172 xcb_drawable_t drawable,
173 __DRIscreen *dri_screen,
174 bool is_different_gpu,
175 const __DRIconfig *dri_config,
176 struct loader_dri3_extensions *ext,
177 struct loader_dri3_vtable *vtable,
178 struct loader_dri3_drawable*);
179
180 bool loader_dri3_wait_for_msc(struct loader_dri3_drawable *draw,
181 int64_t target_msc,
182 int64_t divisor, int64_t remainder,
183 int64_t *ust, int64_t *msc, int64_t *sbc);
184
185 int64_t
186 loader_dri3_swap_buffers_msc(struct loader_dri3_drawable *draw,
187 int64_t target_msc, int64_t divisor,
188 int64_t remainder, unsigned flush_flags,
189 bool force_copy);
190
191 int
192 loader_dri3_wait_for_sbc(struct loader_dri3_drawable *draw,
193 int64_t target_sbc, int64_t *ust,
194 int64_t *msc, int64_t *sbc);
195
196 int loader_dri3_query_buffer_age(struct loader_dri3_drawable *draw);
197
198 void
199 loader_dri3_flush(struct loader_dri3_drawable *draw,
200 unsigned flags,
201 enum __DRI2throttleReason throttle_reason);
202
203 void
204 loader_dri3_copy_sub_buffer(struct loader_dri3_drawable *draw,
205 int x, int y,
206 int width, int height,
207 bool flush);
208
209 void
210 loader_dri3_copy_drawable(struct loader_dri3_drawable *draw,
211 xcb_drawable_t dest,
212 xcb_drawable_t src);
213
214 void
215 loader_dri3_wait_x(struct loader_dri3_drawable *draw);
216
217 void
218 loader_dri3_wait_gl(struct loader_dri3_drawable *draw);
219
220 int loader_dri3_open(xcb_connection_t *conn,
221 xcb_window_t root,
222 uint32_t provider);
223
224 int
225 loader_dri3_get_buffers(__DRIdrawable *driDrawable,
226 unsigned int format,
227 uint32_t *stamp,
228 void *loaderPrivate,
229 uint32_t buffer_mask,
230 struct __DRIimageList *buffers);
231
232 #endif