2 * Copyright © 2013 Keith Packard
3 * Copyright © 2015 Boyan Ding
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.
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
24 #ifndef LOADER_DRI3_HEADER_H
25 #define LOADER_DRI3_HEADER_H
32 #include <xcb/present.h>
35 #include <GL/internal/dri_interface.h>
36 #include <c11/threads.h>
38 enum loader_dri3_buffer_type
{
39 loader_dri3_buffer_back
= 0,
40 loader_dri3_buffer_front
= 1
43 struct loader_dri3_buffer
{
45 __DRIimage
*linear_buffer
;
48 /* Synchronization between the client and X server is done using an
49 * xshmfence that is mapped into an X server SyncFence. This lets the
50 * client check whether the X server is done using a buffer with a simple
51 * xshmfence call, rather than going to read X events from the wire.
53 * However, we can only wait for one xshmfence to be triggered at a time,
54 * so we need to know *which* buffer is going to be idle next. We do that
55 * by waiting for a PresentIdleNotify event. When that event arrives, the
56 * 'busy' flag gets cleared and the client knows that the fence has been
57 * triggered, and that the wait call will not block.
60 uint32_t sync_fence
; /* XID of X SyncFence object */
61 struct xshmfence
*shm_fence
; /* pointer to xshmfence object */
62 bool busy
; /* Set on swap, cleared on IdleNotify */
63 bool own_pixmap
; /* We allocated the pixmap ID, free on destroy */
64 bool reallocate
; /* Buffer should be reallocated and not reused */
73 uint32_t width
, height
;
78 #define LOADER_DRI3_MAX_BACK 4
79 #define LOADER_DRI3_BACK_ID(i) (i)
80 #define LOADER_DRI3_FRONT_ID (LOADER_DRI3_MAX_BACK)
83 loader_dri3_pixmap_buf_id(enum loader_dri3_buffer_type buffer_type
)
85 if (buffer_type
== loader_dri3_buffer_back
)
86 return LOADER_DRI3_BACK_ID(0);
88 return LOADER_DRI3_FRONT_ID
;
91 struct loader_dri3_extensions
{
92 const __DRIcoreExtension
*core
;
93 const __DRIimageDriverExtension
*image_driver
;
94 const __DRI2flushExtension
*flush
;
95 const __DRI2configQueryExtension
*config
;
96 const __DRItexBufferExtension
*tex_buffer
;
97 const __DRIimageExtension
*image
;
100 struct loader_dri3_drawable
;
102 struct loader_dri3_vtable
{
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
)(void);
107 void (*flush_drawable
)(struct loader_dri3_drawable
*, unsigned);
108 void (*show_fps
)(struct loader_dri3_drawable
*, uint64_t);
111 #define LOADER_DRI3_NUM_BUFFERS (1 + LOADER_DRI3_MAX_BACK)
113 struct loader_dri3_drawable
{
114 xcb_connection_t
*conn
;
115 xcb_screen_t
*screen
;
116 __DRIdrawable
*dri_drawable
;
117 xcb_drawable_t drawable
;
123 uint8_t have_fake_front
;
126 /* Information about the GPU owning the buffer */
127 __DRIscreen
*dri_screen
;
128 bool is_different_gpu
;
129 bool multiplanes_available
;
131 /* Present extension capabilities
133 uint32_t present_capabilities
;
135 /* SBC numbers are tracked by using the serial numbers
136 * in the present request and complete events
141 /* Last received UST/MSC values for pixmap present complete */
144 /* Last received UST/MSC values from present notify msc event */
145 uint64_t notify_ust
, notify_msc
;
147 struct loader_dri3_buffer
*buffers
[LOADER_DRI3_NUM_BUFFERS
];
154 xcb_present_event_t eid
;
156 xcb_special_event_t
*special_event
;
161 struct loader_dri3_extensions
*ext
;
162 const struct loader_dri3_vtable
*vtable
;
164 unsigned int swap_method
;
165 unsigned int back_format
;
166 xcb_present_complete_mode_t last_present_mode
;
168 /* Currently protects the following fields:
169 * event_cnd, has_event_waiter,
170 * recv_sbc, ust, msc, recv_msc_serial,
171 * notify_ust, notify_msc
175 bool has_event_waiter
;
179 loader_dri3_set_swap_interval(struct loader_dri3_drawable
*draw
,
183 loader_dri3_drawable_fini(struct loader_dri3_drawable
*draw
);
186 loader_dri3_drawable_init(xcb_connection_t
*conn
,
187 xcb_drawable_t drawable
,
188 __DRIscreen
*dri_screen
,
189 bool is_different_gpu
,
190 bool is_multiplanes_available
,
191 const __DRIconfig
*dri_config
,
192 struct loader_dri3_extensions
*ext
,
193 const struct loader_dri3_vtable
*vtable
,
194 struct loader_dri3_drawable
*);
196 bool loader_dri3_wait_for_msc(struct loader_dri3_drawable
*draw
,
198 int64_t divisor
, int64_t remainder
,
199 int64_t *ust
, int64_t *msc
, int64_t *sbc
);
202 loader_dri3_swap_buffers_msc(struct loader_dri3_drawable
*draw
,
203 int64_t target_msc
, int64_t divisor
,
204 int64_t remainder
, unsigned flush_flags
,
208 loader_dri3_wait_for_sbc(struct loader_dri3_drawable
*draw
,
209 int64_t target_sbc
, int64_t *ust
,
210 int64_t *msc
, int64_t *sbc
);
212 int loader_dri3_query_buffer_age(struct loader_dri3_drawable
*draw
);
215 loader_dri3_flush(struct loader_dri3_drawable
*draw
,
217 enum __DRI2throttleReason throttle_reason
);
220 loader_dri3_copy_sub_buffer(struct loader_dri3_drawable
*draw
,
222 int width
, int height
,
226 loader_dri3_copy_drawable(struct loader_dri3_drawable
*draw
,
231 loader_dri3_wait_x(struct loader_dri3_drawable
*draw
);
234 loader_dri3_wait_gl(struct loader_dri3_drawable
*draw
);
236 int loader_dri3_open(xcb_connection_t
*conn
,
241 loader_dri3_create_image(xcb_connection_t
*c
,
242 xcb_dri3_buffer_from_pixmap_reply_t
*bp_reply
,
244 __DRIscreen
*dri_screen
,
245 const __DRIimageExtension
*image
,
246 void *loaderPrivate
);
248 #ifdef HAVE_DRI3_MODIFIERS
250 loader_dri3_create_image_from_buffers(xcb_connection_t
*c
,
251 xcb_dri3_buffers_from_pixmap_reply_t
*bp_reply
,
253 __DRIscreen
*dri_screen
,
254 const __DRIimageExtension
*image
,
255 void *loaderPrivate
);
258 loader_dri3_get_buffers(__DRIdrawable
*driDrawable
,
262 uint32_t buffer_mask
,
263 struct __DRIimageList
*buffers
);
266 loader_dri3_update_drawable_geometry(struct loader_dri3_drawable
*draw
);
269 loader_dri3_swapbuffer_barrier(struct loader_dri3_drawable
*draw
);
272 loader_dri3_close_screen(__DRIscreen
*dri_screen
);