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 37enum loader_dri3_buffer_type { 38 loader_dri3_buffer_back = 0, 39 loader_dri3_buffer_front = 1 40}; 41 42struct loader_dri3_buffer { 43 __DRIimage *image; 44 __DRIimage *linear_buffer; 45 uint32_t pixmap; 46 47 /* Synchronization between the client and X server is done using an 48 * xshmfence that is mapped into an X server SyncFence. This lets the 49 * client check whether the X server is done using a buffer with a simple 50 * xshmfence call, rather than going to read X events from the wire. 51 * 52 * However, we can only wait for one xshmfence to be triggered at a time, 53 * so we need to know *which* buffer is going to be idle next. We do that 54 * by waiting for a PresentIdleNotify event. When that event arrives, the 55 * 'busy' flag gets cleared and the client knows that the fence has been 56 * triggered, and that the wait call will not block. 57 */ 58 59 uint32_t sync_fence; /* XID of X SyncFence object */ 60 struct xshmfence *shm_fence; /* pointer to xshmfence object */ 61 bool busy; /* Set on swap, cleared on IdleNotify */ 62 bool own_pixmap; /* We allocated the pixmap ID, free on destroy */ 63 64 uint32_t size; 65 uint32_t pitch; 66 uint32_t cpp; 67 uint32_t flags; 68 uint32_t width, height; 69 uint64_t last_swap; 70 71 enum loader_dri3_buffer_type buffer_type; 72}; 73 74 75#define LOADER_DRI3_MAX_BACK 4 76#define LOADER_DRI3_BACK_ID(i) (i) 77#define LOADER_DRI3_FRONT_ID (LOADER_DRI3_MAX_BACK) 78 79static inline int 80loader_dri3_pixmap_buf_id(enum loader_dri3_buffer_type buffer_type) 81{ 82 if (buffer_type == loader_dri3_buffer_back) 83 return LOADER_DRI3_BACK_ID(0); 84 else 85 return LOADER_DRI3_FRONT_ID; 86} 87 88struct loader_dri3_extensions { 89 const __DRIcoreExtension *core; 90 const __DRIimageDriverExtension *image_driver; 91 const __DRI2flushExtension *flush; 92 const __DRI2configQueryExtension *config; 93 const __DRItexBufferExtension *tex_buffer; 94 const __DRIimageExtension *image; 95}; 96 97struct loader_dri3_drawable; 98 99struct loader_dri3_vtable { 100 int (*get_swap_interval)(struct loader_dri3_drawable *); 101 int (*clamp_swap_interval)(struct loader_dri3_drawable *, int); 102 void (*set_swap_interval)(struct loader_dri3_drawable *, int); 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)(struct loader_dri3_drawable *); 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 __DRIdrawable *dri_drawable; 116 xcb_drawable_t drawable; 117 int width; 118 int height; 119 int depth; 120 uint8_t have_back; 121 uint8_t have_fake_front; 122 uint8_t is_pixmap; 123 uint8_t flipping; 124 125 /* Information about the GPU owning the buffer */ 126 __DRIscreen *dri_screen; 127 bool is_different_gpu; 128 129 /* Present extension capabilities 130 */ 131 uint32_t present_capabilities; 132 133 /* SBC numbers are tracked by using the serial numbers 134 * in the present request and complete events 135 */ 136 uint64_t send_sbc; 137 uint64_t recv_sbc; 138 139 /* Last received UST/MSC values for pixmap present complete */ 140 uint64_t ust, msc; 141 142 /* Last received UST/MSC values from present notify msc event */ 143 uint64_t notify_ust, notify_msc; 144 145 /* Serial numbers for tracking wait_for_msc events */ 146 uint32_t send_msc_serial; 147 uint32_t recv_msc_serial; 148 149 struct loader_dri3_buffer *buffers[LOADER_DRI3_NUM_BUFFERS]; 150 int cur_back; 151 int num_back; 152 153 uint32_t *stamp; 154 155 xcb_present_event_t eid; 156 xcb_gcontext_t gc; 157 xcb_special_event_t *special_event; 158 159 bool first_init; 160 161 struct loader_dri3_extensions *ext; 162 const struct loader_dri3_vtable *vtable; 163}; 164 165void 166loader_dri3_set_swap_interval(struct loader_dri3_drawable *draw, 167 int interval); 168 169void 170loader_dri3_drawable_fini(struct loader_dri3_drawable *draw); 171 172int 173loader_dri3_drawable_init(xcb_connection_t *conn, 174 xcb_drawable_t drawable, 175 __DRIscreen *dri_screen, 176 bool is_different_gpu, 177 const __DRIconfig *dri_config, 178 struct loader_dri3_extensions *ext, 179 const struct loader_dri3_vtable *vtable, 180 struct loader_dri3_drawable*); 181 182bool loader_dri3_wait_for_msc(struct loader_dri3_drawable *draw, 183 int64_t target_msc, 184 int64_t divisor, int64_t remainder, 185 int64_t *ust, int64_t *msc, int64_t *sbc); 186 187int64_t 188loader_dri3_swap_buffers_msc(struct loader_dri3_drawable *draw, 189 int64_t target_msc, int64_t divisor, 190 int64_t remainder, unsigned flush_flags, 191 bool force_copy); 192 193int 194loader_dri3_wait_for_sbc(struct loader_dri3_drawable *draw, 195 int64_t target_sbc, int64_t *ust, 196 int64_t *msc, int64_t *sbc); 197 198int loader_dri3_query_buffer_age(struct loader_dri3_drawable *draw); 199 200void 201loader_dri3_flush(struct loader_dri3_drawable *draw, 202 unsigned flags, 203 enum __DRI2throttleReason throttle_reason); 204 205void 206loader_dri3_copy_sub_buffer(struct loader_dri3_drawable *draw, 207 int x, int y, 208 int width, int height, 209 bool flush); 210 211void 212loader_dri3_copy_drawable(struct loader_dri3_drawable *draw, 213 xcb_drawable_t dest, 214 xcb_drawable_t src); 215 216void 217loader_dri3_wait_x(struct loader_dri3_drawable *draw); 218 219void 220loader_dri3_wait_gl(struct loader_dri3_drawable *draw); 221 222int loader_dri3_open(xcb_connection_t *conn, 223 xcb_window_t root, 224 uint32_t provider); 225 226__DRIimage * 227loader_dri3_create_image(xcb_connection_t *c, 228 xcb_dri3_buffer_from_pixmap_reply_t *bp_reply, 229 unsigned int format, 230 __DRIscreen *dri_screen, 231 const __DRIimageExtension *image, 232 void *loaderPrivate); 233 234int 235loader_dri3_get_buffers(__DRIdrawable *driDrawable, 236 unsigned int format, 237 uint32_t *stamp, 238 void *loaderPrivate, 239 uint32_t buffer_mask, 240 struct __DRIimageList *buffers); 241 242void 243loader_dri3_update_drawable_geometry(struct loader_dri3_drawable *draw); 244#endif 245