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