• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <GL/internal/dri_interface.h>
36 #include <c11/threads.h>
37 
38 enum loader_dri3_buffer_type {
39    loader_dri3_buffer_back = 0,
40    loader_dri3_buffer_front = 1
41 };
42 
43 struct loader_dri3_buffer {
44    __DRIimage   *image;
45    uint32_t     pixmap;
46 
47    /* default case: linear buffer allocated in render gpu vram.
48     * p2p case: linear buffer allocated in display gpu vram and imported
49     *           to render gpu. p2p case is enabled when driver name matches
50     *           while creating screen in dri3_create_screen() function.
51     */
52    __DRIimage   *linear_buffer;
53 
54    /* Synchronization between the client and X server is done using an
55     * xshmfence that is mapped into an X server SyncFence. This lets the
56     * client check whether the X server is done using a buffer with a simple
57     * xshmfence call, rather than going to read X events from the wire.
58     *
59     * However, we can only wait for one xshmfence to be triggered at a time,
60     * so we need to know *which* buffer is going to be idle next. We do that
61     * by waiting for a PresentIdleNotify event. When that event arrives, the
62     * 'busy' flag gets cleared and the client knows that the fence has been
63     * triggered, and that the wait call will not block.
64     */
65 
66    uint32_t     sync_fence;     /* XID of X SyncFence object */
67    struct xshmfence *shm_fence; /* pointer to xshmfence object */
68    bool         busy;           /* Set on swap, cleared on IdleNotify */
69    bool         own_pixmap;     /* We allocated the pixmap ID, free on destroy */
70    bool         reallocate;     /* Buffer should be reallocated and not reused */
71 
72    uint32_t     num_planes;
73    uint32_t     size;
74    int          strides[4];
75    int          offsets[4];
76    uint64_t     modifier;
77    uint32_t     cpp;
78    uint32_t     flags;
79    uint32_t     width, height;
80    uint64_t     last_swap;
81 };
82 
83 
84 #define LOADER_DRI3_MAX_BACK   4
85 #define LOADER_DRI3_BACK_ID(i) (i)
86 #define LOADER_DRI3_FRONT_ID   (LOADER_DRI3_MAX_BACK)
87 
88 static inline int
loader_dri3_pixmap_buf_id(enum loader_dri3_buffer_type buffer_type)89 loader_dri3_pixmap_buf_id(enum loader_dri3_buffer_type buffer_type)
90 {
91    if (buffer_type == loader_dri3_buffer_back)
92       return LOADER_DRI3_BACK_ID(0);
93    else
94       return LOADER_DRI3_FRONT_ID;
95 }
96 
97 struct loader_dri3_extensions {
98    const __DRIcoreExtension *core;
99    const __DRIimageDriverExtension *image_driver;
100    const __DRI2flushExtension *flush;
101    const __DRI2configQueryExtension *config;
102    const __DRItexBufferExtension *tex_buffer;
103    const __DRIimageExtension *image;
104 };
105 
106 struct loader_dri3_drawable;
107 
108 struct loader_dri3_vtable {
109    void (*set_drawable_size)(struct loader_dri3_drawable *, int, int);
110    bool (*in_current_context)(struct loader_dri3_drawable *);
111    __DRIcontext *(*get_dri_context)(struct loader_dri3_drawable *);
112    __DRIscreen *(*get_dri_screen)(void);
113    void (*flush_drawable)(struct loader_dri3_drawable *, unsigned);
114 };
115 
116 #define LOADER_DRI3_NUM_BUFFERS (1 + LOADER_DRI3_MAX_BACK)
117 
118 enum loader_dri3_drawable_type {
119    LOADER_DRI3_DRAWABLE_UNKNOWN,
120    LOADER_DRI3_DRAWABLE_WINDOW,
121    LOADER_DRI3_DRAWABLE_PIXMAP,
122    LOADER_DRI3_DRAWABLE_PBUFFER,
123 };
124 
125 struct loader_dri3_drawable {
126    xcb_connection_t *conn;
127    xcb_screen_t *screen;
128    __DRIdrawable *dri_drawable;
129    xcb_drawable_t drawable;
130    xcb_window_t window;
131    xcb_xfixes_region_t region;
132    int width;
133    int height;
134    int depth;
135    uint8_t have_back;
136    uint8_t have_fake_front;
137    enum loader_dri3_drawable_type type;
138 
139    /* Information about the GPU owning the buffer */
140    bool multiplanes_available;
141    bool prefer_back_buffer_reuse;
142    __DRIscreen *dri_screen_render_gpu;
143    /* dri_screen_display_gpu holds display GPU in case of prime gpu offloading else
144     * dri_screen_render_gpu and dri_screen_display_gpu is same.
145     * In case of prime gpu offloading, if display and render driver names are different
146     * (potentially not compatible), dri_screen_display_gpu will be NULL but fd_display_gpu
147     * will still hold fd for display driver.
148     */
149    __DRIscreen *dri_screen_display_gpu;
150 
151    /* SBC numbers are tracked by using the serial numbers
152     * in the present request and complete events
153     */
154    uint64_t send_sbc;
155    uint64_t recv_sbc;
156 
157    /* Last received UST/MSC values for pixmap present complete */
158    uint64_t ust, msc;
159 
160    /* Last received UST/MSC values from present notify msc event */
161    uint64_t notify_ust, notify_msc;
162 
163    struct loader_dri3_buffer *buffers[LOADER_DRI3_NUM_BUFFERS];
164    int cur_back;
165    int cur_num_back;
166    int max_num_back;
167    int cur_blit_source;
168 
169    uint32_t *stamp;
170 
171    xcb_present_event_t eid;
172    xcb_gcontext_t gc;
173    xcb_special_event_t *special_event;
174 
175    bool first_init;
176    bool adaptive_sync;
177    bool adaptive_sync_active;
178    bool block_on_depleted_buffers;
179    bool queries_buffer_age;
180    int swap_interval;
181 
182    struct loader_dri3_extensions *ext;
183    const struct loader_dri3_vtable *vtable;
184 
185    unsigned int back_format;
186    xcb_present_complete_mode_t last_present_mode;
187 
188    bool is_protected_content;
189 
190    /* Currently protects the following fields:
191     * event_cnd, has_event_waiter,
192     * recv_sbc, ust, msc, recv_msc_serial,
193     * notify_ust, notify_msc
194     */
195    mtx_t mtx;
196    cnd_t event_cnd;
197    unsigned last_special_event_sequence;
198    bool has_event_waiter;
199 };
200 
201 void
202 loader_dri3_set_swap_interval(struct loader_dri3_drawable *draw,
203                               int interval);
204 
205 void
206 loader_dri3_drawable_fini(struct loader_dri3_drawable *draw);
207 
208 int
209 loader_dri3_drawable_init(xcb_connection_t *conn,
210                           xcb_drawable_t drawable,
211                           enum loader_dri3_drawable_type type,
212                           __DRIscreen *dri_screen_render_gpu,
213                           __DRIscreen *dri_screen_display_gpu,
214                           bool is_multiplanes_available,
215                           bool prefer_back_buffer_reuse,
216                           const __DRIconfig *dri_config,
217                           struct loader_dri3_extensions *ext,
218                           const struct loader_dri3_vtable *vtable,
219                           struct loader_dri3_drawable*);
220 
221 bool loader_dri3_wait_for_msc(struct loader_dri3_drawable *draw,
222                               int64_t target_msc,
223                               int64_t divisor, int64_t remainder,
224                               int64_t *ust, int64_t *msc, int64_t *sbc);
225 
226 int64_t
227 loader_dri3_swap_buffers_msc(struct loader_dri3_drawable *draw,
228                              int64_t target_msc, int64_t divisor,
229                              int64_t remainder, unsigned flush_flags,
230                              const int *rects, int n_rects,
231                              bool force_copy);
232 
233 int
234 loader_dri3_wait_for_sbc(struct loader_dri3_drawable *draw,
235                          int64_t target_sbc, int64_t *ust,
236                          int64_t *msc, int64_t *sbc);
237 
238 int loader_dri3_query_buffer_age(struct loader_dri3_drawable *draw);
239 
240 void
241 loader_dri3_flush(struct loader_dri3_drawable *draw,
242                   unsigned flags,
243                   enum __DRI2throttleReason throttle_reason);
244 
245 void
246 loader_dri3_copy_sub_buffer(struct loader_dri3_drawable *draw,
247                             int x, int y,
248                             int width, int height,
249                             bool flush);
250 
251 void
252 loader_dri3_copy_drawable(struct loader_dri3_drawable *draw,
253                           xcb_drawable_t dest,
254                           xcb_drawable_t src);
255 
256 void
257 loader_dri3_wait_x(struct loader_dri3_drawable *draw);
258 
259 void
260 loader_dri3_wait_gl(struct loader_dri3_drawable *draw);
261 
262 int loader_dri3_open(xcb_connection_t *conn,
263                      xcb_window_t root,
264                      uint32_t provider);
265 
266 __DRIimage *
267 loader_dri3_create_image(xcb_connection_t *c,
268                          xcb_dri3_buffer_from_pixmap_reply_t *bp_reply,
269                          unsigned int format,
270                          __DRIscreen *dri_screen,
271                          const __DRIimageExtension *image,
272                          void *loaderPrivate);
273 
274 #ifdef HAVE_DRI3_MODIFIERS
275 __DRIimage *
276 loader_dri3_create_image_from_buffers(xcb_connection_t *c,
277                                       xcb_dri3_buffers_from_pixmap_reply_t *bp_reply,
278                                       unsigned int format,
279                                       __DRIscreen *dri_screen,
280                                       const __DRIimageExtension *image,
281                                       void *loaderPrivate);
282 #endif
283 int
284 loader_dri3_get_buffers(__DRIdrawable *driDrawable,
285                         unsigned int format,
286                         uint32_t *stamp,
287                         void *loaderPrivate,
288                         uint32_t buffer_mask,
289                         struct __DRIimageList *buffers);
290 
291 void
292 loader_dri3_update_drawable_geometry(struct loader_dri3_drawable *draw);
293 
294 void
295 loader_dri3_swapbuffer_barrier(struct loader_dri3_drawable *draw);
296 
297 void
298 loader_dri3_close_screen(__DRIscreen *dri_screen);
299 
300 #endif
301