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