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