loader_dri3_helper.h revision 9f464c52
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 __DRIimage *linear_buffer; 46 uint32_t pixmap; 47 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. 52 * 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. 58 */ 59 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 */ 65 66 uint32_t num_planes; 67 uint32_t size; 68 int strides[4]; 69 int offsets[4]; 70 uint64_t modifier; 71 uint32_t cpp; 72 uint32_t flags; 73 uint32_t width, height; 74 uint64_t last_swap; 75}; 76 77 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) 81 82static inline int 83loader_dri3_pixmap_buf_id(enum loader_dri3_buffer_type buffer_type) 84{ 85 if (buffer_type == loader_dri3_buffer_back) 86 return LOADER_DRI3_BACK_ID(0); 87 else 88 return LOADER_DRI3_FRONT_ID; 89} 90 91struct 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; 98}; 99 100struct loader_dri3_drawable; 101 102struct 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); 109}; 110 111#define LOADER_DRI3_NUM_BUFFERS (1 + LOADER_DRI3_MAX_BACK) 112 113struct loader_dri3_drawable { 114 xcb_connection_t *conn; 115 xcb_screen_t *screen; 116 __DRIdrawable *dri_drawable; 117 xcb_drawable_t drawable; 118 xcb_window_t window; 119 int width; 120 int height; 121 int depth; 122 uint8_t have_back; 123 uint8_t have_fake_front; 124 uint8_t is_pixmap; 125 126 /* Information about the GPU owning the buffer */ 127 __DRIscreen *dri_screen; 128 bool is_different_gpu; 129 bool multiplanes_available; 130 131 /* Present extension capabilities 132 */ 133 uint32_t present_capabilities; 134 135 /* SBC numbers are tracked by using the serial numbers 136 * in the present request and complete events 137 */ 138 uint64_t send_sbc; 139 uint64_t recv_sbc; 140 141 /* Last received UST/MSC values for pixmap present complete */ 142 uint64_t ust, msc; 143 144 /* Last received UST/MSC values from present notify msc event */ 145 uint64_t notify_ust, notify_msc; 146 147 struct loader_dri3_buffer *buffers[LOADER_DRI3_NUM_BUFFERS]; 148 int cur_back; 149 int num_back; 150 int cur_blit_source; 151 152 uint32_t *stamp; 153 154 xcb_present_event_t eid; 155 xcb_gcontext_t gc; 156 xcb_special_event_t *special_event; 157 158 bool first_init; 159 bool adaptive_sync; 160 bool adaptive_sync_active; 161 int swap_interval; 162 163 struct loader_dri3_extensions *ext; 164 const struct loader_dri3_vtable *vtable; 165 166 unsigned int swap_method; 167 unsigned int back_format; 168 xcb_present_complete_mode_t last_present_mode; 169 170 /* Currently protects the following fields: 171 * event_cnd, has_event_waiter, 172 * recv_sbc, ust, msc, recv_msc_serial, 173 * notify_ust, notify_msc 174 */ 175 mtx_t mtx; 176 cnd_t event_cnd; 177 bool has_event_waiter; 178}; 179 180void 181loader_dri3_set_swap_interval(struct loader_dri3_drawable *draw, 182 int interval); 183 184void 185loader_dri3_drawable_fini(struct loader_dri3_drawable *draw); 186 187int 188loader_dri3_drawable_init(xcb_connection_t *conn, 189 xcb_drawable_t drawable, 190 __DRIscreen *dri_screen, 191 bool is_different_gpu, 192 bool is_multiplanes_available, 193 const __DRIconfig *dri_config, 194 struct loader_dri3_extensions *ext, 195 const struct loader_dri3_vtable *vtable, 196 struct loader_dri3_drawable*); 197 198bool loader_dri3_wait_for_msc(struct loader_dri3_drawable *draw, 199 int64_t target_msc, 200 int64_t divisor, int64_t remainder, 201 int64_t *ust, int64_t *msc, int64_t *sbc); 202 203int64_t 204loader_dri3_swap_buffers_msc(struct loader_dri3_drawable *draw, 205 int64_t target_msc, int64_t divisor, 206 int64_t remainder, unsigned flush_flags, 207 bool force_copy); 208 209int 210loader_dri3_wait_for_sbc(struct loader_dri3_drawable *draw, 211 int64_t target_sbc, int64_t *ust, 212 int64_t *msc, int64_t *sbc); 213 214int loader_dri3_query_buffer_age(struct loader_dri3_drawable *draw); 215 216void 217loader_dri3_flush(struct loader_dri3_drawable *draw, 218 unsigned flags, 219 enum __DRI2throttleReason throttle_reason); 220 221void 222loader_dri3_copy_sub_buffer(struct loader_dri3_drawable *draw, 223 int x, int y, 224 int width, int height, 225 bool flush); 226 227void 228loader_dri3_copy_drawable(struct loader_dri3_drawable *draw, 229 xcb_drawable_t dest, 230 xcb_drawable_t src); 231 232void 233loader_dri3_wait_x(struct loader_dri3_drawable *draw); 234 235void 236loader_dri3_wait_gl(struct loader_dri3_drawable *draw); 237 238int loader_dri3_open(xcb_connection_t *conn, 239 xcb_window_t root, 240 uint32_t provider); 241 242__DRIimage * 243loader_dri3_create_image(xcb_connection_t *c, 244 xcb_dri3_buffer_from_pixmap_reply_t *bp_reply, 245 unsigned int format, 246 __DRIscreen *dri_screen, 247 const __DRIimageExtension *image, 248 void *loaderPrivate); 249 250#ifdef HAVE_DRI3_MODIFIERS 251__DRIimage * 252loader_dri3_create_image_from_buffers(xcb_connection_t *c, 253 xcb_dri3_buffers_from_pixmap_reply_t *bp_reply, 254 unsigned int format, 255 __DRIscreen *dri_screen, 256 const __DRIimageExtension *image, 257 void *loaderPrivate); 258#endif 259int 260loader_dri3_get_buffers(__DRIdrawable *driDrawable, 261 unsigned int format, 262 uint32_t *stamp, 263 void *loaderPrivate, 264 uint32_t buffer_mask, 265 struct __DRIimageList *buffers); 266 267void 268loader_dri3_update_drawable_geometry(struct loader_dri3_drawable *draw); 269 270void 271loader_dri3_swapbuffer_barrier(struct loader_dri3_drawable *draw); 272 273void 274loader_dri3_close_screen(__DRIscreen *dri_screen); 275#endif 276