1b8e80941Smrg/* 2b8e80941Smrg * Copyright © 2013 Keith Packard 3b8e80941Smrg * Copyright © 2015 Boyan Ding 4b8e80941Smrg * 5b8e80941Smrg * Permission to use, copy, modify, distribute, and sell this software and its 6b8e80941Smrg * documentation for any purpose is hereby granted without fee, provided that 7b8e80941Smrg * the above copyright notice appear in all copies and that both that copyright 8b8e80941Smrg * notice and this permission notice appear in supporting documentation, and 9b8e80941Smrg * that the name of the copyright holders not be used in advertising or 10b8e80941Smrg * publicity pertaining to distribution of the software without specific, 11b8e80941Smrg * written prior permission. The copyright holders make no representations 12b8e80941Smrg * about the suitability of this software for any purpose. It is provided "as 13b8e80941Smrg * is" without express or implied warranty. 14b8e80941Smrg * 15b8e80941Smrg * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 16b8e80941Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 17b8e80941Smrg * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 18b8e80941Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 19b8e80941Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 20b8e80941Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 21b8e80941Smrg * OF THIS SOFTWARE. 22b8e80941Smrg */ 23b8e80941Smrg 24b8e80941Smrg#ifndef LOADER_DRI3_HEADER_H 25b8e80941Smrg#define LOADER_DRI3_HEADER_H 26b8e80941Smrg 27b8e80941Smrg#include <stdbool.h> 28b8e80941Smrg#include <stdint.h> 29b8e80941Smrg 30b8e80941Smrg#include <xcb/xcb.h> 31b8e80941Smrg#include <xcb/dri3.h> 32b8e80941Smrg#include <xcb/present.h> 33b8e80941Smrg 34b8e80941Smrg#include <GL/gl.h> 35b8e80941Smrg#include <GL/internal/dri_interface.h> 36b8e80941Smrg#include <c11/threads.h> 37b8e80941Smrg 38b8e80941Smrgenum loader_dri3_buffer_type { 39b8e80941Smrg loader_dri3_buffer_back = 0, 40b8e80941Smrg loader_dri3_buffer_front = 1 41b8e80941Smrg}; 42b8e80941Smrg 43b8e80941Smrgstruct loader_dri3_buffer { 44b8e80941Smrg __DRIimage *image; 45b8e80941Smrg __DRIimage *linear_buffer; 46b8e80941Smrg uint32_t pixmap; 47b8e80941Smrg 48b8e80941Smrg /* Synchronization between the client and X server is done using an 49b8e80941Smrg * xshmfence that is mapped into an X server SyncFence. This lets the 50b8e80941Smrg * client check whether the X server is done using a buffer with a simple 51b8e80941Smrg * xshmfence call, rather than going to read X events from the wire. 52b8e80941Smrg * 53b8e80941Smrg * However, we can only wait for one xshmfence to be triggered at a time, 54b8e80941Smrg * so we need to know *which* buffer is going to be idle next. We do that 55b8e80941Smrg * by waiting for a PresentIdleNotify event. When that event arrives, the 56b8e80941Smrg * 'busy' flag gets cleared and the client knows that the fence has been 57b8e80941Smrg * triggered, and that the wait call will not block. 58b8e80941Smrg */ 59b8e80941Smrg 60b8e80941Smrg uint32_t sync_fence; /* XID of X SyncFence object */ 61b8e80941Smrg struct xshmfence *shm_fence; /* pointer to xshmfence object */ 62b8e80941Smrg bool busy; /* Set on swap, cleared on IdleNotify */ 63b8e80941Smrg bool own_pixmap; /* We allocated the pixmap ID, free on destroy */ 64b8e80941Smrg bool reallocate; /* Buffer should be reallocated and not reused */ 65b8e80941Smrg 66b8e80941Smrg uint32_t num_planes; 67b8e80941Smrg uint32_t size; 68b8e80941Smrg int strides[4]; 69b8e80941Smrg int offsets[4]; 70b8e80941Smrg uint64_t modifier; 71b8e80941Smrg uint32_t cpp; 72b8e80941Smrg uint32_t flags; 73b8e80941Smrg uint32_t width, height; 74b8e80941Smrg uint64_t last_swap; 75b8e80941Smrg}; 76b8e80941Smrg 77b8e80941Smrg 78b8e80941Smrg#define LOADER_DRI3_MAX_BACK 4 79b8e80941Smrg#define LOADER_DRI3_BACK_ID(i) (i) 80b8e80941Smrg#define LOADER_DRI3_FRONT_ID (LOADER_DRI3_MAX_BACK) 81b8e80941Smrg 82b8e80941Smrgstatic inline int 83b8e80941Smrgloader_dri3_pixmap_buf_id(enum loader_dri3_buffer_type buffer_type) 84b8e80941Smrg{ 85b8e80941Smrg if (buffer_type == loader_dri3_buffer_back) 86b8e80941Smrg return LOADER_DRI3_BACK_ID(0); 87b8e80941Smrg else 88b8e80941Smrg return LOADER_DRI3_FRONT_ID; 89b8e80941Smrg} 90b8e80941Smrg 91b8e80941Smrgstruct loader_dri3_extensions { 92b8e80941Smrg const __DRIcoreExtension *core; 93b8e80941Smrg const __DRIimageDriverExtension *image_driver; 94b8e80941Smrg const __DRI2flushExtension *flush; 95b8e80941Smrg const __DRI2configQueryExtension *config; 96b8e80941Smrg const __DRItexBufferExtension *tex_buffer; 97b8e80941Smrg const __DRIimageExtension *image; 98b8e80941Smrg}; 99b8e80941Smrg 100b8e80941Smrgstruct loader_dri3_drawable; 101b8e80941Smrg 102b8e80941Smrgstruct loader_dri3_vtable { 103b8e80941Smrg void (*set_drawable_size)(struct loader_dri3_drawable *, int, int); 104b8e80941Smrg bool (*in_current_context)(struct loader_dri3_drawable *); 105b8e80941Smrg __DRIcontext *(*get_dri_context)(struct loader_dri3_drawable *); 106b8e80941Smrg __DRIscreen *(*get_dri_screen)(void); 107b8e80941Smrg void (*flush_drawable)(struct loader_dri3_drawable *, unsigned); 108b8e80941Smrg void (*show_fps)(struct loader_dri3_drawable *, uint64_t); 109b8e80941Smrg}; 110b8e80941Smrg 111b8e80941Smrg#define LOADER_DRI3_NUM_BUFFERS (1 + LOADER_DRI3_MAX_BACK) 112b8e80941Smrg 113b8e80941Smrgstruct loader_dri3_drawable { 114b8e80941Smrg xcb_connection_t *conn; 115b8e80941Smrg xcb_screen_t *screen; 116b8e80941Smrg __DRIdrawable *dri_drawable; 117b8e80941Smrg xcb_drawable_t drawable; 118b8e80941Smrg xcb_window_t window; 119b8e80941Smrg int width; 120b8e80941Smrg int height; 121b8e80941Smrg int depth; 122b8e80941Smrg uint8_t have_back; 123b8e80941Smrg uint8_t have_fake_front; 124b8e80941Smrg uint8_t is_pixmap; 125b8e80941Smrg 126b8e80941Smrg /* Information about the GPU owning the buffer */ 127b8e80941Smrg __DRIscreen *dri_screen; 128b8e80941Smrg bool is_different_gpu; 129b8e80941Smrg bool multiplanes_available; 130b8e80941Smrg 131b8e80941Smrg /* Present extension capabilities 132b8e80941Smrg */ 133b8e80941Smrg uint32_t present_capabilities; 134b8e80941Smrg 135b8e80941Smrg /* SBC numbers are tracked by using the serial numbers 136b8e80941Smrg * in the present request and complete events 137b8e80941Smrg */ 138b8e80941Smrg uint64_t send_sbc; 139b8e80941Smrg uint64_t recv_sbc; 140b8e80941Smrg 141b8e80941Smrg /* Last received UST/MSC values for pixmap present complete */ 142b8e80941Smrg uint64_t ust, msc; 143b8e80941Smrg 144b8e80941Smrg /* Last received UST/MSC values from present notify msc event */ 145b8e80941Smrg uint64_t notify_ust, notify_msc; 146b8e80941Smrg 147b8e80941Smrg struct loader_dri3_buffer *buffers[LOADER_DRI3_NUM_BUFFERS]; 148b8e80941Smrg int cur_back; 149b8e80941Smrg int num_back; 150b8e80941Smrg int cur_blit_source; 151b8e80941Smrg 152b8e80941Smrg uint32_t *stamp; 153b8e80941Smrg 154b8e80941Smrg xcb_present_event_t eid; 155b8e80941Smrg xcb_gcontext_t gc; 156b8e80941Smrg xcb_special_event_t *special_event; 157b8e80941Smrg 158b8e80941Smrg bool first_init; 159b8e80941Smrg bool adaptive_sync; 160b8e80941Smrg bool adaptive_sync_active; 161b8e80941Smrg int swap_interval; 162b8e80941Smrg 163b8e80941Smrg struct loader_dri3_extensions *ext; 164b8e80941Smrg const struct loader_dri3_vtable *vtable; 165b8e80941Smrg 166b8e80941Smrg unsigned int swap_method; 167b8e80941Smrg unsigned int back_format; 168b8e80941Smrg xcb_present_complete_mode_t last_present_mode; 169b8e80941Smrg 170b8e80941Smrg /* Currently protects the following fields: 171b8e80941Smrg * event_cnd, has_event_waiter, 172b8e80941Smrg * recv_sbc, ust, msc, recv_msc_serial, 173b8e80941Smrg * notify_ust, notify_msc 174b8e80941Smrg */ 175b8e80941Smrg mtx_t mtx; 176b8e80941Smrg cnd_t event_cnd; 177b8e80941Smrg bool has_event_waiter; 178b8e80941Smrg}; 179b8e80941Smrg 180b8e80941Smrgvoid 181b8e80941Smrgloader_dri3_set_swap_interval(struct loader_dri3_drawable *draw, 182b8e80941Smrg int interval); 183b8e80941Smrg 184b8e80941Smrgvoid 185b8e80941Smrgloader_dri3_drawable_fini(struct loader_dri3_drawable *draw); 186b8e80941Smrg 187b8e80941Smrgint 188b8e80941Smrgloader_dri3_drawable_init(xcb_connection_t *conn, 189b8e80941Smrg xcb_drawable_t drawable, 190b8e80941Smrg __DRIscreen *dri_screen, 191b8e80941Smrg bool is_different_gpu, 192b8e80941Smrg bool is_multiplanes_available, 193b8e80941Smrg const __DRIconfig *dri_config, 194b8e80941Smrg struct loader_dri3_extensions *ext, 195b8e80941Smrg const struct loader_dri3_vtable *vtable, 196b8e80941Smrg struct loader_dri3_drawable*); 197b8e80941Smrg 198b8e80941Smrgbool loader_dri3_wait_for_msc(struct loader_dri3_drawable *draw, 199b8e80941Smrg int64_t target_msc, 200b8e80941Smrg int64_t divisor, int64_t remainder, 201b8e80941Smrg int64_t *ust, int64_t *msc, int64_t *sbc); 202b8e80941Smrg 203b8e80941Smrgint64_t 204b8e80941Smrgloader_dri3_swap_buffers_msc(struct loader_dri3_drawable *draw, 205b8e80941Smrg int64_t target_msc, int64_t divisor, 206b8e80941Smrg int64_t remainder, unsigned flush_flags, 207b8e80941Smrg bool force_copy); 208b8e80941Smrg 209b8e80941Smrgint 210b8e80941Smrgloader_dri3_wait_for_sbc(struct loader_dri3_drawable *draw, 211b8e80941Smrg int64_t target_sbc, int64_t *ust, 212b8e80941Smrg int64_t *msc, int64_t *sbc); 213b8e80941Smrg 214b8e80941Smrgint loader_dri3_query_buffer_age(struct loader_dri3_drawable *draw); 215b8e80941Smrg 216b8e80941Smrgvoid 217b8e80941Smrgloader_dri3_flush(struct loader_dri3_drawable *draw, 218b8e80941Smrg unsigned flags, 219b8e80941Smrg enum __DRI2throttleReason throttle_reason); 220b8e80941Smrg 221b8e80941Smrgvoid 222b8e80941Smrgloader_dri3_copy_sub_buffer(struct loader_dri3_drawable *draw, 223b8e80941Smrg int x, int y, 224b8e80941Smrg int width, int height, 225b8e80941Smrg bool flush); 226b8e80941Smrg 227b8e80941Smrgvoid 228b8e80941Smrgloader_dri3_copy_drawable(struct loader_dri3_drawable *draw, 229b8e80941Smrg xcb_drawable_t dest, 230b8e80941Smrg xcb_drawable_t src); 231b8e80941Smrg 232b8e80941Smrgvoid 233b8e80941Smrgloader_dri3_wait_x(struct loader_dri3_drawable *draw); 234b8e80941Smrg 235b8e80941Smrgvoid 236b8e80941Smrgloader_dri3_wait_gl(struct loader_dri3_drawable *draw); 237b8e80941Smrg 238b8e80941Smrgint loader_dri3_open(xcb_connection_t *conn, 239b8e80941Smrg xcb_window_t root, 240b8e80941Smrg uint32_t provider); 241b8e80941Smrg 242b8e80941Smrg__DRIimage * 243b8e80941Smrgloader_dri3_create_image(xcb_connection_t *c, 244b8e80941Smrg xcb_dri3_buffer_from_pixmap_reply_t *bp_reply, 245b8e80941Smrg unsigned int format, 246b8e80941Smrg __DRIscreen *dri_screen, 247b8e80941Smrg const __DRIimageExtension *image, 248b8e80941Smrg void *loaderPrivate); 249b8e80941Smrg 250b8e80941Smrg#ifdef HAVE_DRI3_MODIFIERS 251b8e80941Smrg__DRIimage * 252b8e80941Smrgloader_dri3_create_image_from_buffers(xcb_connection_t *c, 253b8e80941Smrg xcb_dri3_buffers_from_pixmap_reply_t *bp_reply, 254b8e80941Smrg unsigned int format, 255b8e80941Smrg __DRIscreen *dri_screen, 256b8e80941Smrg const __DRIimageExtension *image, 257b8e80941Smrg void *loaderPrivate); 258b8e80941Smrg#endif 259b8e80941Smrgint 260b8e80941Smrgloader_dri3_get_buffers(__DRIdrawable *driDrawable, 261b8e80941Smrg unsigned int format, 262b8e80941Smrg uint32_t *stamp, 263b8e80941Smrg void *loaderPrivate, 264b8e80941Smrg uint32_t buffer_mask, 265b8e80941Smrg struct __DRIimageList *buffers); 266b8e80941Smrg 267b8e80941Smrgvoid 268b8e80941Smrgloader_dri3_update_drawable_geometry(struct loader_dri3_drawable *draw); 269b8e80941Smrg 270b8e80941Smrgvoid 271b8e80941Smrgloader_dri3_swapbuffer_barrier(struct loader_dri3_drawable *draw); 272b8e80941Smrg 273b8e80941Smrgvoid 274b8e80941Smrgloader_dri3_close_screen(__DRIscreen *dri_screen); 275b8e80941Smrg#endif 276