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#include <c11/threads.h> 37 38enum loader_dri3_buffer_type { 39 loader_dri3_buffer_back = 0, 40 loader_dri3_buffer_front = 1 41}; 42 43struct loader_dri3_buffer { 44 __DRIimage *image; 45 uint32_t pixmap; 46 47 /* default case: linear buffer allocated in render gpu vram. 48 * p2p case: linear buffer allocated in display gpu vram and imported 49 * to render gpu. p2p case is enabled when driver name matches 50 * while creating screen in dri3_create_screen() function. 51 */ 52 __DRIimage *linear_buffer; 53 54 /* Synchronization between the client and X server is done using an 55 * xshmfence that is mapped into an X server SyncFence. This lets the 56 * client check whether the X server is done using a buffer with a simple 57 * xshmfence call, rather than going to read X events from the wire. 58 * 59 * However, we can only wait for one xshmfence to be triggered at a time, 60 * so we need to know *which* buffer is going to be idle next. We do that 61 * by waiting for a PresentIdleNotify event. When that event arrives, the 62 * 'busy' flag gets cleared and the client knows that the fence has been 63 * triggered, and that the wait call will not block. 64 */ 65 66 uint32_t sync_fence; /* XID of X SyncFence object */ 67 struct xshmfence *shm_fence; /* pointer to xshmfence object */ 68 bool busy; /* Set on swap, cleared on IdleNotify */ 69 bool own_pixmap; /* We allocated the pixmap ID, free on destroy */ 70 bool reallocate; /* Buffer should be reallocated and not reused */ 71 72 uint32_t num_planes; 73 uint32_t size; 74 int strides[4]; 75 int offsets[4]; 76 uint64_t modifier; 77 uint32_t cpp; 78 uint32_t flags; 79 uint32_t width, height; 80 uint64_t last_swap; 81}; 82 83 84#define LOADER_DRI3_MAX_BACK 4 85#define LOADER_DRI3_BACK_ID(i) (i) 86#define LOADER_DRI3_FRONT_ID (LOADER_DRI3_MAX_BACK) 87 88static inline int 89loader_dri3_pixmap_buf_id(enum loader_dri3_buffer_type buffer_type) 90{ 91 if (buffer_type == loader_dri3_buffer_back) 92 return LOADER_DRI3_BACK_ID(0); 93 else 94 return LOADER_DRI3_FRONT_ID; 95} 96 97struct loader_dri3_extensions { 98 const __DRIcoreExtension *core; 99 const __DRIimageDriverExtension *image_driver; 100 const __DRI2flushExtension *flush; 101 const __DRI2configQueryExtension *config; 102 const __DRItexBufferExtension *tex_buffer; 103 const __DRIimageExtension *image; 104}; 105 106struct loader_dri3_drawable; 107 108struct loader_dri3_vtable { 109 void (*set_drawable_size)(struct loader_dri3_drawable *, int, int); 110 bool (*in_current_context)(struct loader_dri3_drawable *); 111 __DRIcontext *(*get_dri_context)(struct loader_dri3_drawable *); 112 __DRIscreen *(*get_dri_screen)(void); 113 void (*flush_drawable)(struct loader_dri3_drawable *, unsigned); 114 void (*show_fps)(struct loader_dri3_drawable *, uint64_t); 115}; 116 117#define LOADER_DRI3_NUM_BUFFERS (1 + LOADER_DRI3_MAX_BACK) 118 119enum loader_dri3_drawable_type { 120 LOADER_DRI3_DRAWABLE_UNKNOWN, 121 LOADER_DRI3_DRAWABLE_WINDOW, 122 LOADER_DRI3_DRAWABLE_PIXMAP, 123 LOADER_DRI3_DRAWABLE_PBUFFER, 124}; 125 126struct loader_dri3_drawable { 127 xcb_connection_t *conn; 128 xcb_screen_t *screen; 129 __DRIdrawable *dri_drawable; 130 xcb_drawable_t drawable; 131 xcb_window_t window; 132 xcb_xfixes_region_t region; 133 int width; 134 int height; 135 int depth; 136 uint8_t have_back; 137 uint8_t have_fake_front; 138 enum loader_dri3_drawable_type type; 139 140 /* Information about the GPU owning the buffer */ 141 __DRIscreen *dri_screen; 142 bool is_different_gpu; 143 bool multiplanes_available; 144 bool prefer_back_buffer_reuse; 145 146 /* DRI screen created for display GPU in case of prime */ 147 __DRIscreen *dri_screen_display_gpu; 148 149 /* SBC numbers are tracked by using the serial numbers 150 * in the present request and complete events 151 */ 152 uint64_t send_sbc; 153 uint64_t recv_sbc; 154 155 /* Last received UST/MSC values for pixmap present complete */ 156 uint64_t ust, msc; 157 158 /* Last received UST/MSC values from present notify msc event */ 159 uint64_t notify_ust, notify_msc; 160 161 struct loader_dri3_buffer *buffers[LOADER_DRI3_NUM_BUFFERS]; 162 int cur_back; 163 int cur_num_back; 164 int max_num_back; 165 int cur_blit_source; 166 167 uint32_t *stamp; 168 169 xcb_present_event_t eid; 170 xcb_gcontext_t gc; 171 xcb_special_event_t *special_event; 172 173 bool first_init; 174 bool adaptive_sync; 175 bool adaptive_sync_active; 176 int swap_interval; 177 178 struct loader_dri3_extensions *ext; 179 const struct loader_dri3_vtable *vtable; 180 181 unsigned int swap_method; 182 unsigned int back_format; 183 xcb_present_complete_mode_t last_present_mode; 184 185 bool is_protected_content; 186 187 /* Currently protects the following fields: 188 * event_cnd, has_event_waiter, 189 * recv_sbc, ust, msc, recv_msc_serial, 190 * notify_ust, notify_msc 191 */ 192 mtx_t mtx; 193 cnd_t event_cnd; 194 unsigned last_special_event_sequence; 195 bool has_event_waiter; 196}; 197 198void 199loader_dri3_set_swap_interval(struct loader_dri3_drawable *draw, 200 int interval); 201 202void 203loader_dri3_drawable_fini(struct loader_dri3_drawable *draw); 204 205int 206loader_dri3_drawable_init(xcb_connection_t *conn, 207 xcb_drawable_t drawable, 208 enum loader_dri3_drawable_type type, 209 __DRIscreen *dri_screen, 210 bool is_different_gpu, 211 bool is_multiplanes_available, 212 bool prefer_back_buffer_reuse, 213 const __DRIconfig *dri_config, 214 struct loader_dri3_extensions *ext, 215 const struct loader_dri3_vtable *vtable, 216 struct loader_dri3_drawable*); 217 218bool loader_dri3_wait_for_msc(struct loader_dri3_drawable *draw, 219 int64_t target_msc, 220 int64_t divisor, int64_t remainder, 221 int64_t *ust, int64_t *msc, int64_t *sbc); 222 223int64_t 224loader_dri3_swap_buffers_msc(struct loader_dri3_drawable *draw, 225 int64_t target_msc, int64_t divisor, 226 int64_t remainder, unsigned flush_flags, 227 const int *rects, int n_rects, 228 bool force_copy); 229 230int 231loader_dri3_wait_for_sbc(struct loader_dri3_drawable *draw, 232 int64_t target_sbc, int64_t *ust, 233 int64_t *msc, int64_t *sbc); 234 235int loader_dri3_query_buffer_age(struct loader_dri3_drawable *draw); 236 237void 238loader_dri3_flush(struct loader_dri3_drawable *draw, 239 unsigned flags, 240 enum __DRI2throttleReason throttle_reason); 241 242void 243loader_dri3_copy_sub_buffer(struct loader_dri3_drawable *draw, 244 int x, int y, 245 int width, int height, 246 bool flush); 247 248void 249loader_dri3_copy_drawable(struct loader_dri3_drawable *draw, 250 xcb_drawable_t dest, 251 xcb_drawable_t src); 252 253void 254loader_dri3_wait_x(struct loader_dri3_drawable *draw); 255 256void 257loader_dri3_wait_gl(struct loader_dri3_drawable *draw); 258 259int loader_dri3_open(xcb_connection_t *conn, 260 xcb_window_t root, 261 uint32_t provider); 262 263__DRIimage * 264loader_dri3_create_image(xcb_connection_t *c, 265 xcb_dri3_buffer_from_pixmap_reply_t *bp_reply, 266 unsigned int format, 267 __DRIscreen *dri_screen, 268 const __DRIimageExtension *image, 269 void *loaderPrivate); 270 271#ifdef HAVE_DRI3_MODIFIERS 272__DRIimage * 273loader_dri3_create_image_from_buffers(xcb_connection_t *c, 274 xcb_dri3_buffers_from_pixmap_reply_t *bp_reply, 275 unsigned int format, 276 __DRIscreen *dri_screen, 277 const __DRIimageExtension *image, 278 void *loaderPrivate); 279#endif 280int 281loader_dri3_get_buffers(__DRIdrawable *driDrawable, 282 unsigned int format, 283 uint32_t *stamp, 284 void *loaderPrivate, 285 uint32_t buffer_mask, 286 struct __DRIimageList *buffers); 287 288void 289loader_dri3_update_drawable_geometry(struct loader_dri3_drawable *draw); 290 291void 292loader_dri3_swapbuffer_barrier(struct loader_dri3_drawable *draw); 293 294void 295loader_dri3_close_screen(__DRIscreen *dri_screen); 296#endif 297