101e04c3fSmrg/* 201e04c3fSmrg * Copyright © 2013 Keith Packard 301e04c3fSmrg * Copyright © 2015 Boyan Ding 401e04c3fSmrg * 501e04c3fSmrg * Permission to use, copy, modify, distribute, and sell this software and its 601e04c3fSmrg * documentation for any purpose is hereby granted without fee, provided that 701e04c3fSmrg * the above copyright notice appear in all copies and that both that copyright 801e04c3fSmrg * notice and this permission notice appear in supporting documentation, and 901e04c3fSmrg * that the name of the copyright holders not be used in advertising or 1001e04c3fSmrg * publicity pertaining to distribution of the software without specific, 1101e04c3fSmrg * written prior permission. The copyright holders make no representations 1201e04c3fSmrg * about the suitability of this software for any purpose. It is provided "as 1301e04c3fSmrg * is" without express or implied warranty. 1401e04c3fSmrg * 1501e04c3fSmrg * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 1601e04c3fSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 1701e04c3fSmrg * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 1801e04c3fSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 1901e04c3fSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 2001e04c3fSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 2101e04c3fSmrg * OF THIS SOFTWARE. 2201e04c3fSmrg */ 2301e04c3fSmrg 2401e04c3fSmrg#ifndef LOADER_DRI3_HEADER_H 2501e04c3fSmrg#define LOADER_DRI3_HEADER_H 2601e04c3fSmrg 2701e04c3fSmrg#include <stdbool.h> 2801e04c3fSmrg#include <stdint.h> 2901e04c3fSmrg 3001e04c3fSmrg#include <xcb/xcb.h> 3101e04c3fSmrg#include <xcb/dri3.h> 3201e04c3fSmrg#include <xcb/present.h> 3301e04c3fSmrg 3401e04c3fSmrg#include <GL/gl.h> 3501e04c3fSmrg#include <GL/internal/dri_interface.h> 3601e04c3fSmrg#include <c11/threads.h> 3701e04c3fSmrg 3801e04c3fSmrgenum loader_dri3_buffer_type { 3901e04c3fSmrg loader_dri3_buffer_back = 0, 4001e04c3fSmrg loader_dri3_buffer_front = 1 4101e04c3fSmrg}; 4201e04c3fSmrg 4301e04c3fSmrgstruct loader_dri3_buffer { 4401e04c3fSmrg __DRIimage *image; 4501e04c3fSmrg uint32_t pixmap; 4601e04c3fSmrg 477ec681f3Smrg /* default case: linear buffer allocated in render gpu vram. 487ec681f3Smrg * p2p case: linear buffer allocated in display gpu vram and imported 497ec681f3Smrg * to render gpu. p2p case is enabled when driver name matches 507ec681f3Smrg * while creating screen in dri3_create_screen() function. 517ec681f3Smrg */ 527ec681f3Smrg __DRIimage *linear_buffer; 537ec681f3Smrg 5401e04c3fSmrg /* Synchronization between the client and X server is done using an 5501e04c3fSmrg * xshmfence that is mapped into an X server SyncFence. This lets the 5601e04c3fSmrg * client check whether the X server is done using a buffer with a simple 5701e04c3fSmrg * xshmfence call, rather than going to read X events from the wire. 5801e04c3fSmrg * 5901e04c3fSmrg * However, we can only wait for one xshmfence to be triggered at a time, 6001e04c3fSmrg * so we need to know *which* buffer is going to be idle next. We do that 6101e04c3fSmrg * by waiting for a PresentIdleNotify event. When that event arrives, the 6201e04c3fSmrg * 'busy' flag gets cleared and the client knows that the fence has been 6301e04c3fSmrg * triggered, and that the wait call will not block. 6401e04c3fSmrg */ 6501e04c3fSmrg 6601e04c3fSmrg uint32_t sync_fence; /* XID of X SyncFence object */ 6701e04c3fSmrg struct xshmfence *shm_fence; /* pointer to xshmfence object */ 6801e04c3fSmrg bool busy; /* Set on swap, cleared on IdleNotify */ 6901e04c3fSmrg bool own_pixmap; /* We allocated the pixmap ID, free on destroy */ 7001e04c3fSmrg bool reallocate; /* Buffer should be reallocated and not reused */ 7101e04c3fSmrg 7201e04c3fSmrg uint32_t num_planes; 7301e04c3fSmrg uint32_t size; 7401e04c3fSmrg int strides[4]; 7501e04c3fSmrg int offsets[4]; 7601e04c3fSmrg uint64_t modifier; 7701e04c3fSmrg uint32_t cpp; 7801e04c3fSmrg uint32_t flags; 7901e04c3fSmrg uint32_t width, height; 8001e04c3fSmrg uint64_t last_swap; 8101e04c3fSmrg}; 8201e04c3fSmrg 8301e04c3fSmrg 8401e04c3fSmrg#define LOADER_DRI3_MAX_BACK 4 8501e04c3fSmrg#define LOADER_DRI3_BACK_ID(i) (i) 8601e04c3fSmrg#define LOADER_DRI3_FRONT_ID (LOADER_DRI3_MAX_BACK) 8701e04c3fSmrg 8801e04c3fSmrgstatic inline int 8901e04c3fSmrgloader_dri3_pixmap_buf_id(enum loader_dri3_buffer_type buffer_type) 9001e04c3fSmrg{ 9101e04c3fSmrg if (buffer_type == loader_dri3_buffer_back) 9201e04c3fSmrg return LOADER_DRI3_BACK_ID(0); 9301e04c3fSmrg else 9401e04c3fSmrg return LOADER_DRI3_FRONT_ID; 9501e04c3fSmrg} 9601e04c3fSmrg 9701e04c3fSmrgstruct loader_dri3_extensions { 9801e04c3fSmrg const __DRIcoreExtension *core; 9901e04c3fSmrg const __DRIimageDriverExtension *image_driver; 10001e04c3fSmrg const __DRI2flushExtension *flush; 10101e04c3fSmrg const __DRI2configQueryExtension *config; 10201e04c3fSmrg const __DRItexBufferExtension *tex_buffer; 10301e04c3fSmrg const __DRIimageExtension *image; 10401e04c3fSmrg}; 10501e04c3fSmrg 10601e04c3fSmrgstruct loader_dri3_drawable; 10701e04c3fSmrg 10801e04c3fSmrgstruct loader_dri3_vtable { 10901e04c3fSmrg void (*set_drawable_size)(struct loader_dri3_drawable *, int, int); 11001e04c3fSmrg bool (*in_current_context)(struct loader_dri3_drawable *); 11101e04c3fSmrg __DRIcontext *(*get_dri_context)(struct loader_dri3_drawable *); 11201e04c3fSmrg __DRIscreen *(*get_dri_screen)(void); 11301e04c3fSmrg void (*flush_drawable)(struct loader_dri3_drawable *, unsigned); 11401e04c3fSmrg void (*show_fps)(struct loader_dri3_drawable *, uint64_t); 11501e04c3fSmrg}; 11601e04c3fSmrg 11701e04c3fSmrg#define LOADER_DRI3_NUM_BUFFERS (1 + LOADER_DRI3_MAX_BACK) 11801e04c3fSmrg 11901e04c3fSmrgstruct loader_dri3_drawable { 12001e04c3fSmrg xcb_connection_t *conn; 12101e04c3fSmrg xcb_screen_t *screen; 12201e04c3fSmrg __DRIdrawable *dri_drawable; 12301e04c3fSmrg xcb_drawable_t drawable; 12401e04c3fSmrg xcb_window_t window; 1257ec681f3Smrg xcb_xfixes_region_t region; 12601e04c3fSmrg int width; 12701e04c3fSmrg int height; 12801e04c3fSmrg int depth; 12901e04c3fSmrg uint8_t have_back; 13001e04c3fSmrg uint8_t have_fake_front; 13101e04c3fSmrg uint8_t is_pixmap; 13201e04c3fSmrg 13301e04c3fSmrg /* Information about the GPU owning the buffer */ 13401e04c3fSmrg __DRIscreen *dri_screen; 13501e04c3fSmrg bool is_different_gpu; 13601e04c3fSmrg bool multiplanes_available; 1377ec681f3Smrg bool prefer_back_buffer_reuse; 1387ec681f3Smrg 1397ec681f3Smrg /* DRI screen created for display GPU in case of prime */ 1407ec681f3Smrg __DRIscreen *dri_screen_display_gpu; 14101e04c3fSmrg 14201e04c3fSmrg /* Present extension capabilities 14301e04c3fSmrg */ 14401e04c3fSmrg uint32_t present_capabilities; 14501e04c3fSmrg 14601e04c3fSmrg /* SBC numbers are tracked by using the serial numbers 14701e04c3fSmrg * in the present request and complete events 14801e04c3fSmrg */ 14901e04c3fSmrg uint64_t send_sbc; 15001e04c3fSmrg uint64_t recv_sbc; 15101e04c3fSmrg 15201e04c3fSmrg /* Last received UST/MSC values for pixmap present complete */ 15301e04c3fSmrg uint64_t ust, msc; 15401e04c3fSmrg 15501e04c3fSmrg /* Last received UST/MSC values from present notify msc event */ 15601e04c3fSmrg uint64_t notify_ust, notify_msc; 15701e04c3fSmrg 15801e04c3fSmrg struct loader_dri3_buffer *buffers[LOADER_DRI3_NUM_BUFFERS]; 15901e04c3fSmrg int cur_back; 1607ec681f3Smrg int cur_num_back; 1617ec681f3Smrg int max_num_back; 16201e04c3fSmrg int cur_blit_source; 16301e04c3fSmrg 16401e04c3fSmrg uint32_t *stamp; 16501e04c3fSmrg 16601e04c3fSmrg xcb_present_event_t eid; 16701e04c3fSmrg xcb_gcontext_t gc; 16801e04c3fSmrg xcb_special_event_t *special_event; 16901e04c3fSmrg 17001e04c3fSmrg bool first_init; 1719f464c52Smaya bool adaptive_sync; 1729f464c52Smaya bool adaptive_sync_active; 17301e04c3fSmrg int swap_interval; 17401e04c3fSmrg 17501e04c3fSmrg struct loader_dri3_extensions *ext; 17601e04c3fSmrg const struct loader_dri3_vtable *vtable; 17701e04c3fSmrg 17801e04c3fSmrg unsigned int swap_method; 17901e04c3fSmrg unsigned int back_format; 18001e04c3fSmrg xcb_present_complete_mode_t last_present_mode; 18101e04c3fSmrg 1827ec681f3Smrg bool is_protected_content; 1837ec681f3Smrg 18401e04c3fSmrg /* Currently protects the following fields: 18501e04c3fSmrg * event_cnd, has_event_waiter, 18601e04c3fSmrg * recv_sbc, ust, msc, recv_msc_serial, 18701e04c3fSmrg * notify_ust, notify_msc 18801e04c3fSmrg */ 18901e04c3fSmrg mtx_t mtx; 19001e04c3fSmrg cnd_t event_cnd; 1917ec681f3Smrg unsigned last_special_event_sequence; 19201e04c3fSmrg bool has_event_waiter; 19301e04c3fSmrg}; 19401e04c3fSmrg 19501e04c3fSmrgvoid 19601e04c3fSmrgloader_dri3_set_swap_interval(struct loader_dri3_drawable *draw, 19701e04c3fSmrg int interval); 19801e04c3fSmrg 19901e04c3fSmrgvoid 20001e04c3fSmrgloader_dri3_drawable_fini(struct loader_dri3_drawable *draw); 20101e04c3fSmrg 20201e04c3fSmrgint 20301e04c3fSmrgloader_dri3_drawable_init(xcb_connection_t *conn, 20401e04c3fSmrg xcb_drawable_t drawable, 20501e04c3fSmrg __DRIscreen *dri_screen, 20601e04c3fSmrg bool is_different_gpu, 20701e04c3fSmrg bool is_multiplanes_available, 2087ec681f3Smrg bool prefer_back_buffer_reuse, 20901e04c3fSmrg const __DRIconfig *dri_config, 21001e04c3fSmrg struct loader_dri3_extensions *ext, 21101e04c3fSmrg const struct loader_dri3_vtable *vtable, 21201e04c3fSmrg struct loader_dri3_drawable*); 21301e04c3fSmrg 21401e04c3fSmrgbool loader_dri3_wait_for_msc(struct loader_dri3_drawable *draw, 21501e04c3fSmrg int64_t target_msc, 21601e04c3fSmrg int64_t divisor, int64_t remainder, 21701e04c3fSmrg int64_t *ust, int64_t *msc, int64_t *sbc); 21801e04c3fSmrg 21901e04c3fSmrgint64_t 22001e04c3fSmrgloader_dri3_swap_buffers_msc(struct loader_dri3_drawable *draw, 22101e04c3fSmrg int64_t target_msc, int64_t divisor, 22201e04c3fSmrg int64_t remainder, unsigned flush_flags, 2237ec681f3Smrg const int *rects, int n_rects, 22401e04c3fSmrg bool force_copy); 22501e04c3fSmrg 22601e04c3fSmrgint 22701e04c3fSmrgloader_dri3_wait_for_sbc(struct loader_dri3_drawable *draw, 22801e04c3fSmrg int64_t target_sbc, int64_t *ust, 22901e04c3fSmrg int64_t *msc, int64_t *sbc); 23001e04c3fSmrg 23101e04c3fSmrgint loader_dri3_query_buffer_age(struct loader_dri3_drawable *draw); 23201e04c3fSmrg 23301e04c3fSmrgvoid 23401e04c3fSmrgloader_dri3_flush(struct loader_dri3_drawable *draw, 23501e04c3fSmrg unsigned flags, 23601e04c3fSmrg enum __DRI2throttleReason throttle_reason); 23701e04c3fSmrg 23801e04c3fSmrgvoid 23901e04c3fSmrgloader_dri3_copy_sub_buffer(struct loader_dri3_drawable *draw, 24001e04c3fSmrg int x, int y, 24101e04c3fSmrg int width, int height, 24201e04c3fSmrg bool flush); 24301e04c3fSmrg 24401e04c3fSmrgvoid 24501e04c3fSmrgloader_dri3_copy_drawable(struct loader_dri3_drawable *draw, 24601e04c3fSmrg xcb_drawable_t dest, 24701e04c3fSmrg xcb_drawable_t src); 24801e04c3fSmrg 24901e04c3fSmrgvoid 25001e04c3fSmrgloader_dri3_wait_x(struct loader_dri3_drawable *draw); 25101e04c3fSmrg 25201e04c3fSmrgvoid 25301e04c3fSmrgloader_dri3_wait_gl(struct loader_dri3_drawable *draw); 25401e04c3fSmrg 25501e04c3fSmrgint loader_dri3_open(xcb_connection_t *conn, 25601e04c3fSmrg xcb_window_t root, 25701e04c3fSmrg uint32_t provider); 25801e04c3fSmrg 25901e04c3fSmrg__DRIimage * 26001e04c3fSmrgloader_dri3_create_image(xcb_connection_t *c, 26101e04c3fSmrg xcb_dri3_buffer_from_pixmap_reply_t *bp_reply, 26201e04c3fSmrg unsigned int format, 26301e04c3fSmrg __DRIscreen *dri_screen, 26401e04c3fSmrg const __DRIimageExtension *image, 26501e04c3fSmrg void *loaderPrivate); 26601e04c3fSmrg 26701e04c3fSmrg#ifdef HAVE_DRI3_MODIFIERS 26801e04c3fSmrg__DRIimage * 26901e04c3fSmrgloader_dri3_create_image_from_buffers(xcb_connection_t *c, 27001e04c3fSmrg xcb_dri3_buffers_from_pixmap_reply_t *bp_reply, 27101e04c3fSmrg unsigned int format, 27201e04c3fSmrg __DRIscreen *dri_screen, 27301e04c3fSmrg const __DRIimageExtension *image, 27401e04c3fSmrg void *loaderPrivate); 27501e04c3fSmrg#endif 27601e04c3fSmrgint 27701e04c3fSmrgloader_dri3_get_buffers(__DRIdrawable *driDrawable, 27801e04c3fSmrg unsigned int format, 27901e04c3fSmrg uint32_t *stamp, 28001e04c3fSmrg void *loaderPrivate, 28101e04c3fSmrg uint32_t buffer_mask, 28201e04c3fSmrg struct __DRIimageList *buffers); 28301e04c3fSmrg 28401e04c3fSmrgvoid 28501e04c3fSmrgloader_dri3_update_drawable_geometry(struct loader_dri3_drawable *draw); 28601e04c3fSmrg 28701e04c3fSmrgvoid 28801e04c3fSmrgloader_dri3_swapbuffer_barrier(struct loader_dri3_drawable *draw); 28901e04c3fSmrg 29001e04c3fSmrgvoid 29101e04c3fSmrgloader_dri3_close_screen(__DRIscreen *dri_screen); 29201e04c3fSmrg#endif 293