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