101e04c3fSmrg/*
201e04c3fSmrg * Copyright © 2013 Keith Packard
301e04c3fSmrg * Copyright © 2015 Boyan Ding
401e04c3fSmrg *
501e04c3fSmrg * Permission to use, copy, modify, distribute, and sell this software and its
601e04c3fSmrg * documentation for any purpose is hereby granted without fee, provided that
701e04c3fSmrg * the above copyright notice appear in all copies and that both that copyright
801e04c3fSmrg * notice and this permission notice appear in supporting documentation, and
901e04c3fSmrg * that the name of the copyright holders not be used in advertising or
1001e04c3fSmrg * publicity pertaining to distribution of the software without specific,
1101e04c3fSmrg * written prior permission.  The copyright holders make no representations
1201e04c3fSmrg * about the suitability of this software for any purpose.  It is provided "as
1301e04c3fSmrg * is" without express or implied warranty.
1401e04c3fSmrg *
1501e04c3fSmrg * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
1601e04c3fSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
1701e04c3fSmrg * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
1801e04c3fSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
1901e04c3fSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
2001e04c3fSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
2101e04c3fSmrg * OF THIS SOFTWARE.
2201e04c3fSmrg */
2301e04c3fSmrg
2401e04c3fSmrg#ifndef LOADER_DRI3_HEADER_H
2501e04c3fSmrg#define LOADER_DRI3_HEADER_H
2601e04c3fSmrg
2701e04c3fSmrg#include <stdbool.h>
2801e04c3fSmrg#include <stdint.h>
2901e04c3fSmrg
3001e04c3fSmrg#include <xcb/xcb.h>
3101e04c3fSmrg#include <xcb/dri3.h>
3201e04c3fSmrg#include <xcb/present.h>
3301e04c3fSmrg
3401e04c3fSmrg#include <GL/gl.h>
3501e04c3fSmrg#include <GL/internal/dri_interface.h>
3601e04c3fSmrg#include <c11/threads.h>
3701e04c3fSmrg
3801e04c3fSmrgenum loader_dri3_buffer_type {
3901e04c3fSmrg   loader_dri3_buffer_back = 0,
4001e04c3fSmrg   loader_dri3_buffer_front = 1
4101e04c3fSmrg};
4201e04c3fSmrg
4301e04c3fSmrgstruct loader_dri3_buffer {
4401e04c3fSmrg   __DRIimage   *image;
4501e04c3fSmrg   uint32_t     pixmap;
4601e04c3fSmrg
477ec681f3Smrg   /* default case: linear buffer allocated in render gpu vram.
487ec681f3Smrg    * p2p case: linear buffer allocated in display gpu vram and imported
497ec681f3Smrg    *           to render gpu. p2p case is enabled when driver name matches
507ec681f3Smrg    *           while creating screen in dri3_create_screen() function.
517ec681f3Smrg    */
527ec681f3Smrg   __DRIimage   *linear_buffer;
537ec681f3Smrg
5401e04c3fSmrg   /* Synchronization between the client and X server is done using an
5501e04c3fSmrg    * xshmfence that is mapped into an X server SyncFence. This lets the
5601e04c3fSmrg    * client check whether the X server is done using a buffer with a simple
5701e04c3fSmrg    * xshmfence call, rather than going to read X events from the wire.
5801e04c3fSmrg    *
5901e04c3fSmrg    * However, we can only wait for one xshmfence to be triggered at a time,
6001e04c3fSmrg    * so we need to know *which* buffer is going to be idle next. We do that
6101e04c3fSmrg    * by waiting for a PresentIdleNotify event. When that event arrives, the
6201e04c3fSmrg    * 'busy' flag gets cleared and the client knows that the fence has been
6301e04c3fSmrg    * triggered, and that the wait call will not block.
6401e04c3fSmrg    */
6501e04c3fSmrg
6601e04c3fSmrg   uint32_t     sync_fence;     /* XID of X SyncFence object */
6701e04c3fSmrg   struct xshmfence *shm_fence; /* pointer to xshmfence object */
6801e04c3fSmrg   bool         busy;           /* Set on swap, cleared on IdleNotify */
6901e04c3fSmrg   bool         own_pixmap;     /* We allocated the pixmap ID, free on destroy */
7001e04c3fSmrg   bool         reallocate;     /* Buffer should be reallocated and not reused */
7101e04c3fSmrg
7201e04c3fSmrg   uint32_t     num_planes;
7301e04c3fSmrg   uint32_t     size;
7401e04c3fSmrg   int          strides[4];
7501e04c3fSmrg   int          offsets[4];
7601e04c3fSmrg   uint64_t     modifier;
7701e04c3fSmrg   uint32_t     cpp;
7801e04c3fSmrg   uint32_t     flags;
7901e04c3fSmrg   uint32_t     width, height;
8001e04c3fSmrg   uint64_t     last_swap;
8101e04c3fSmrg};
8201e04c3fSmrg
8301e04c3fSmrg
8401e04c3fSmrg#define LOADER_DRI3_MAX_BACK   4
8501e04c3fSmrg#define LOADER_DRI3_BACK_ID(i) (i)
8601e04c3fSmrg#define LOADER_DRI3_FRONT_ID   (LOADER_DRI3_MAX_BACK)
8701e04c3fSmrg
8801e04c3fSmrgstatic inline int
8901e04c3fSmrgloader_dri3_pixmap_buf_id(enum loader_dri3_buffer_type buffer_type)
9001e04c3fSmrg{
9101e04c3fSmrg   if (buffer_type == loader_dri3_buffer_back)
9201e04c3fSmrg      return LOADER_DRI3_BACK_ID(0);
9301e04c3fSmrg   else
9401e04c3fSmrg      return LOADER_DRI3_FRONT_ID;
9501e04c3fSmrg}
9601e04c3fSmrg
9701e04c3fSmrgstruct loader_dri3_extensions {
9801e04c3fSmrg   const __DRIcoreExtension *core;
9901e04c3fSmrg   const __DRIimageDriverExtension *image_driver;
10001e04c3fSmrg   const __DRI2flushExtension *flush;
10101e04c3fSmrg   const __DRI2configQueryExtension *config;
10201e04c3fSmrg   const __DRItexBufferExtension *tex_buffer;
10301e04c3fSmrg   const __DRIimageExtension *image;
10401e04c3fSmrg};
10501e04c3fSmrg
10601e04c3fSmrgstruct loader_dri3_drawable;
10701e04c3fSmrg
10801e04c3fSmrgstruct loader_dri3_vtable {
10901e04c3fSmrg   void (*set_drawable_size)(struct loader_dri3_drawable *, int, int);
11001e04c3fSmrg   bool (*in_current_context)(struct loader_dri3_drawable *);
11101e04c3fSmrg   __DRIcontext *(*get_dri_context)(struct loader_dri3_drawable *);
11201e04c3fSmrg   __DRIscreen *(*get_dri_screen)(void);
11301e04c3fSmrg   void (*flush_drawable)(struct loader_dri3_drawable *, unsigned);
11401e04c3fSmrg   void (*show_fps)(struct loader_dri3_drawable *, uint64_t);
11501e04c3fSmrg};
11601e04c3fSmrg
11701e04c3fSmrg#define LOADER_DRI3_NUM_BUFFERS (1 + LOADER_DRI3_MAX_BACK)
11801e04c3fSmrg
11901e04c3fSmrgstruct loader_dri3_drawable {
12001e04c3fSmrg   xcb_connection_t *conn;
12101e04c3fSmrg   xcb_screen_t *screen;
12201e04c3fSmrg   __DRIdrawable *dri_drawable;
12301e04c3fSmrg   xcb_drawable_t drawable;
12401e04c3fSmrg   xcb_window_t window;
1257ec681f3Smrg   xcb_xfixes_region_t region;
12601e04c3fSmrg   int width;
12701e04c3fSmrg   int height;
12801e04c3fSmrg   int depth;
12901e04c3fSmrg   uint8_t have_back;
13001e04c3fSmrg   uint8_t have_fake_front;
13101e04c3fSmrg   uint8_t is_pixmap;
13201e04c3fSmrg
13301e04c3fSmrg   /* Information about the GPU owning the buffer */
13401e04c3fSmrg   __DRIscreen *dri_screen;
13501e04c3fSmrg   bool is_different_gpu;
13601e04c3fSmrg   bool multiplanes_available;
1377ec681f3Smrg   bool prefer_back_buffer_reuse;
1387ec681f3Smrg
1397ec681f3Smrg   /* DRI screen created for display GPU in case of prime */
1407ec681f3Smrg   __DRIscreen *dri_screen_display_gpu;
14101e04c3fSmrg
14201e04c3fSmrg   /* Present extension capabilities
14301e04c3fSmrg    */
14401e04c3fSmrg   uint32_t present_capabilities;
14501e04c3fSmrg
14601e04c3fSmrg   /* SBC numbers are tracked by using the serial numbers
14701e04c3fSmrg    * in the present request and complete events
14801e04c3fSmrg    */
14901e04c3fSmrg   uint64_t send_sbc;
15001e04c3fSmrg   uint64_t recv_sbc;
15101e04c3fSmrg
15201e04c3fSmrg   /* Last received UST/MSC values for pixmap present complete */
15301e04c3fSmrg   uint64_t ust, msc;
15401e04c3fSmrg
15501e04c3fSmrg   /* Last received UST/MSC values from present notify msc event */
15601e04c3fSmrg   uint64_t notify_ust, notify_msc;
15701e04c3fSmrg
15801e04c3fSmrg   struct loader_dri3_buffer *buffers[LOADER_DRI3_NUM_BUFFERS];
15901e04c3fSmrg   int cur_back;
1607ec681f3Smrg   int cur_num_back;
1617ec681f3Smrg   int max_num_back;
16201e04c3fSmrg   int cur_blit_source;
16301e04c3fSmrg
16401e04c3fSmrg   uint32_t *stamp;
16501e04c3fSmrg
16601e04c3fSmrg   xcb_present_event_t eid;
16701e04c3fSmrg   xcb_gcontext_t gc;
16801e04c3fSmrg   xcb_special_event_t *special_event;
16901e04c3fSmrg
17001e04c3fSmrg   bool first_init;
1719f464c52Smaya   bool adaptive_sync;
1729f464c52Smaya   bool adaptive_sync_active;
17301e04c3fSmrg   int swap_interval;
17401e04c3fSmrg
17501e04c3fSmrg   struct loader_dri3_extensions *ext;
17601e04c3fSmrg   const struct loader_dri3_vtable *vtable;
17701e04c3fSmrg
17801e04c3fSmrg   unsigned int swap_method;
17901e04c3fSmrg   unsigned int back_format;
18001e04c3fSmrg   xcb_present_complete_mode_t last_present_mode;
18101e04c3fSmrg
1827ec681f3Smrg   bool is_protected_content;
1837ec681f3Smrg
18401e04c3fSmrg   /* Currently protects the following fields:
18501e04c3fSmrg    * event_cnd, has_event_waiter,
18601e04c3fSmrg    * recv_sbc, ust, msc, recv_msc_serial,
18701e04c3fSmrg    * notify_ust, notify_msc
18801e04c3fSmrg    */
18901e04c3fSmrg   mtx_t mtx;
19001e04c3fSmrg   cnd_t event_cnd;
1917ec681f3Smrg   unsigned last_special_event_sequence;
19201e04c3fSmrg   bool has_event_waiter;
19301e04c3fSmrg};
19401e04c3fSmrg
19501e04c3fSmrgvoid
19601e04c3fSmrgloader_dri3_set_swap_interval(struct loader_dri3_drawable *draw,
19701e04c3fSmrg                              int interval);
19801e04c3fSmrg
19901e04c3fSmrgvoid
20001e04c3fSmrgloader_dri3_drawable_fini(struct loader_dri3_drawable *draw);
20101e04c3fSmrg
20201e04c3fSmrgint
20301e04c3fSmrgloader_dri3_drawable_init(xcb_connection_t *conn,
20401e04c3fSmrg                          xcb_drawable_t drawable,
20501e04c3fSmrg                          __DRIscreen *dri_screen,
20601e04c3fSmrg                          bool is_different_gpu,
20701e04c3fSmrg                          bool is_multiplanes_available,
2087ec681f3Smrg                          bool prefer_back_buffer_reuse,
20901e04c3fSmrg                          const __DRIconfig *dri_config,
21001e04c3fSmrg                          struct loader_dri3_extensions *ext,
21101e04c3fSmrg                          const struct loader_dri3_vtable *vtable,
21201e04c3fSmrg                          struct loader_dri3_drawable*);
21301e04c3fSmrg
21401e04c3fSmrgbool loader_dri3_wait_for_msc(struct loader_dri3_drawable *draw,
21501e04c3fSmrg                              int64_t target_msc,
21601e04c3fSmrg                              int64_t divisor, int64_t remainder,
21701e04c3fSmrg                              int64_t *ust, int64_t *msc, int64_t *sbc);
21801e04c3fSmrg
21901e04c3fSmrgint64_t
22001e04c3fSmrgloader_dri3_swap_buffers_msc(struct loader_dri3_drawable *draw,
22101e04c3fSmrg                             int64_t target_msc, int64_t divisor,
22201e04c3fSmrg                             int64_t remainder, unsigned flush_flags,
2237ec681f3Smrg                             const int *rects, int n_rects,
22401e04c3fSmrg                             bool force_copy);
22501e04c3fSmrg
22601e04c3fSmrgint
22701e04c3fSmrgloader_dri3_wait_for_sbc(struct loader_dri3_drawable *draw,
22801e04c3fSmrg                         int64_t target_sbc, int64_t *ust,
22901e04c3fSmrg                         int64_t *msc, int64_t *sbc);
23001e04c3fSmrg
23101e04c3fSmrgint loader_dri3_query_buffer_age(struct loader_dri3_drawable *draw);
23201e04c3fSmrg
23301e04c3fSmrgvoid
23401e04c3fSmrgloader_dri3_flush(struct loader_dri3_drawable *draw,
23501e04c3fSmrg                  unsigned flags,
23601e04c3fSmrg                  enum __DRI2throttleReason throttle_reason);
23701e04c3fSmrg
23801e04c3fSmrgvoid
23901e04c3fSmrgloader_dri3_copy_sub_buffer(struct loader_dri3_drawable *draw,
24001e04c3fSmrg                            int x, int y,
24101e04c3fSmrg                            int width, int height,
24201e04c3fSmrg                            bool flush);
24301e04c3fSmrg
24401e04c3fSmrgvoid
24501e04c3fSmrgloader_dri3_copy_drawable(struct loader_dri3_drawable *draw,
24601e04c3fSmrg                          xcb_drawable_t dest,
24701e04c3fSmrg                          xcb_drawable_t src);
24801e04c3fSmrg
24901e04c3fSmrgvoid
25001e04c3fSmrgloader_dri3_wait_x(struct loader_dri3_drawable *draw);
25101e04c3fSmrg
25201e04c3fSmrgvoid
25301e04c3fSmrgloader_dri3_wait_gl(struct loader_dri3_drawable *draw);
25401e04c3fSmrg
25501e04c3fSmrgint loader_dri3_open(xcb_connection_t *conn,
25601e04c3fSmrg                     xcb_window_t root,
25701e04c3fSmrg                     uint32_t provider);
25801e04c3fSmrg
25901e04c3fSmrg__DRIimage *
26001e04c3fSmrgloader_dri3_create_image(xcb_connection_t *c,
26101e04c3fSmrg                         xcb_dri3_buffer_from_pixmap_reply_t *bp_reply,
26201e04c3fSmrg                         unsigned int format,
26301e04c3fSmrg                         __DRIscreen *dri_screen,
26401e04c3fSmrg                         const __DRIimageExtension *image,
26501e04c3fSmrg                         void *loaderPrivate);
26601e04c3fSmrg
26701e04c3fSmrg#ifdef HAVE_DRI3_MODIFIERS
26801e04c3fSmrg__DRIimage *
26901e04c3fSmrgloader_dri3_create_image_from_buffers(xcb_connection_t *c,
27001e04c3fSmrg                                      xcb_dri3_buffers_from_pixmap_reply_t *bp_reply,
27101e04c3fSmrg                                      unsigned int format,
27201e04c3fSmrg                                      __DRIscreen *dri_screen,
27301e04c3fSmrg                                      const __DRIimageExtension *image,
27401e04c3fSmrg                                      void *loaderPrivate);
27501e04c3fSmrg#endif
27601e04c3fSmrgint
27701e04c3fSmrgloader_dri3_get_buffers(__DRIdrawable *driDrawable,
27801e04c3fSmrg                        unsigned int format,
27901e04c3fSmrg                        uint32_t *stamp,
28001e04c3fSmrg                        void *loaderPrivate,
28101e04c3fSmrg                        uint32_t buffer_mask,
28201e04c3fSmrg                        struct __DRIimageList *buffers);
28301e04c3fSmrg
28401e04c3fSmrgvoid
28501e04c3fSmrgloader_dri3_update_drawable_geometry(struct loader_dri3_drawable *draw);
28601e04c3fSmrg
28701e04c3fSmrgvoid
28801e04c3fSmrgloader_dri3_swapbuffer_barrier(struct loader_dri3_drawable *draw);
28901e04c3fSmrg
29001e04c3fSmrgvoid
29101e04c3fSmrgloader_dri3_close_screen(__DRIscreen *dri_screen);
29201e04c3fSmrg#endif
293