1/* 2 * Copyright © 2011 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 * DEALINGS IN THE SOFTWARE. 23 * 24 * Authors: 25 * Kristian Høgsberg <krh@bitplanet.net> 26 */ 27 28#ifndef EGL_DRI2_INCLUDED 29#define EGL_DRI2_INCLUDED 30 31#include <stdbool.h> 32#include <stdint.h> 33 34#ifdef HAVE_X11_PLATFORM 35#include <xcb/xcb.h> 36#include <xcb/dri2.h> 37#include <xcb/xfixes.h> 38#include <X11/Xlib-xcb.h> 39 40#ifdef HAVE_DRI3 41#include "loader_dri3_helper.h" 42#endif 43#endif 44 45#ifdef HAVE_WAYLAND_PLATFORM 46/* forward declarations to avoid pulling wayland headers everywhere */ 47struct wl_egl_window; 48struct wl_event_queue; 49struct wl_callback; 50struct wl_display; 51struct wl_drm; 52struct wl_registry; 53struct wl_shm; 54struct wl_surface; 55struct zwp_linux_dmabuf_v1; 56#endif 57 58#include <GL/gl.h> 59#include <GL/internal/dri_interface.h> 60 61#ifdef HAVE_DRM_PLATFORM 62#include <gbm_driint.h> 63#endif 64 65#ifdef HAVE_ANDROID_PLATFORM 66#define LOG_TAG "EGL-DRI2" 67 68#include <hardware/gralloc.h> 69 70#if ANDROID_API_LEVEL >= 26 71#include <vndk/window.h> 72#else 73#include <system/window.h> 74#endif 75 76#endif /* HAVE_ANDROID_PLATFORM */ 77 78#include "eglconfig.h" 79#include "eglcontext.h" 80#include "egldevice.h" 81#include "egldisplay.h" 82#include "egldriver.h" 83#include "eglcurrent.h" 84#include "egllog.h" 85#include "eglsurface.h" 86#include "eglimage.h" 87#include "eglsync.h" 88 89#include "util/u_vector.h" 90#include "util/bitset.h" 91 92#define EGL_DRI2_MAX_FORMATS 11 93 94struct wl_buffer; 95 96struct dri2_egl_display_vtbl { 97 /* mandatory on Wayland, unused otherwise */ 98 int (*authenticate)(_EGLDisplay *disp, uint32_t id); 99 100 /* mandatory */ 101 _EGLSurface* (*create_window_surface)(_EGLDisplay *disp, _EGLConfig *config, 102 void *native_window, 103 const EGLint *attrib_list); 104 105 /* optional */ 106 _EGLSurface* (*create_pixmap_surface)(_EGLDisplay *disp, _EGLConfig *config, 107 void *native_pixmap, 108 const EGLint *attrib_list); 109 110 /* optional */ 111 _EGLSurface* (*create_pbuffer_surface)(_EGLDisplay *disp, _EGLConfig *config, 112 const EGLint *attrib_list); 113 114 /* mandatory */ 115 EGLBoolean (*destroy_surface)(_EGLDisplay *disp, _EGLSurface *surface); 116 117 /* optional */ 118 EGLBoolean (*swap_interval)(_EGLDisplay *disp, _EGLSurface *surf, 119 EGLint interval); 120 121 /* mandatory */ 122 _EGLImage* (*create_image)(_EGLDisplay *disp, _EGLContext *ctx, 123 EGLenum target, EGLClientBuffer buffer, 124 const EGLint *attr_list); 125 126 /* mandatory */ 127 EGLBoolean (*swap_buffers)(_EGLDisplay *disp, _EGLSurface *surf); 128 129 /* optional - falls back to .swap_buffers */ 130 EGLBoolean (*swap_buffers_with_damage)(_EGLDisplay *disp, _EGLSurface *surface, 131 const EGLint *rects, EGLint n_rects); 132 133 /* optional */ 134 EGLBoolean (*swap_buffers_region)(_EGLDisplay *disp, _EGLSurface *surf, 135 EGLint numRects, const EGLint *rects); 136 137 /* optional */ 138 EGLBoolean (*post_sub_buffer)(_EGLDisplay *disp, _EGLSurface *surf, 139 EGLint x, EGLint y, 140 EGLint width, EGLint height); 141 142 /* optional */ 143 EGLBoolean (*copy_buffers)(_EGLDisplay *disp, _EGLSurface *surf, 144 void *native_pixmap_target); 145 146 /* optional */ 147 EGLint (*query_buffer_age)(_EGLDisplay *disp, _EGLSurface *surf); 148 149 /* optional */ 150 EGLBoolean (*query_surface)(_EGLDisplay *disp, _EGLSurface *surf, 151 EGLint attribute, EGLint *value); 152 153 /* optional */ 154 struct wl_buffer* (*create_wayland_buffer_from_image)(_EGLDisplay *disp, 155 _EGLImage *img); 156 157 /* optional */ 158 EGLBoolean (*get_sync_values)(_EGLDisplay *display, _EGLSurface *surface, 159 EGLuint64KHR *ust, EGLuint64KHR *msc, 160 EGLuint64KHR *sbc); 161 162 /* mandatory */ 163 __DRIdrawable *(*get_dri_drawable)(_EGLSurface *surf); 164 165 /* optional */ 166 void (*close_screen_notify)(_EGLDisplay *disp); 167 168 /* Used in EGL_KHR_mutable_render_buffer to update the native window's 169 * shared buffer mode. 170 * optional 171 */ 172 bool (*set_shared_buffer_mode)(_EGLDisplay *disp, _EGLSurface *surf, 173 bool mode); 174}; 175 176struct dri2_egl_display 177{ 178 const struct dri2_egl_display_vtbl *vtbl; 179 180 int dri2_major; 181 int dri2_minor; 182 __DRIscreen *dri_screen; 183 bool own_dri_screen; 184 const __DRIconfig **driver_configs; 185 void *driver; 186 const __DRIcoreExtension *core; 187 const __DRIimageDriverExtension *image_driver; 188 const __DRIdri2Extension *dri2; 189 const __DRIswrastExtension *swrast; 190 const __DRI2flushExtension *flush; 191 const __DRI2flushControlExtension *flush_control; 192 const __DRItexBufferExtension *tex_buffer; 193 const __DRIimageExtension *image; 194 const __DRIrobustnessExtension *robustness; 195 const __DRInoErrorExtension *no_error; 196 const __DRI2configQueryExtension *config; 197 const __DRI2fenceExtension *fence; 198 const __DRI2bufferDamageExtension *buffer_damage; 199 const __DRI2blobExtension *blob; 200 const __DRI2rendererQueryExtension *rendererQuery; 201 const __DRI2interopExtension *interop; 202 const __DRIconfigOptionsExtension *configOptions; 203 const __DRImutableRenderBufferDriverExtension *mutable_render_buffer; 204 int fd; 205 206 /* dri2_initialize/dri2_terminate increment/decrement this count, so does 207 * dri2_make_current (tracks if there are active contexts/surfaces). */ 208 int ref_count; 209 210 bool own_device; 211 bool invalidate_available; 212 int min_swap_interval; 213 int max_swap_interval; 214 int default_swap_interval; 215#ifdef HAVE_DRM_PLATFORM 216 struct gbm_dri_device *gbm_dri; 217#endif 218 219 char *driver_name; 220 221 const __DRIextension **loader_extensions; 222 const __DRIextension **driver_extensions; 223 224#ifdef HAVE_X11_PLATFORM 225 xcb_connection_t *conn; 226 xcb_screen_t *screen; 227 bool swap_available; 228#ifdef HAVE_DRI3 229 bool multibuffers_available; 230 int dri3_major_version; 231 int dri3_minor_version; 232 int present_major_version; 233 int present_minor_version; 234 struct loader_dri3_extensions loader_dri3_ext; 235#endif 236#endif 237 238#ifdef HAVE_WAYLAND_PLATFORM 239 struct wl_display *wl_dpy; 240 struct wl_display *wl_dpy_wrapper; 241 struct wl_registry *wl_registry; 242 struct wl_drm *wl_server_drm; 243 struct wl_drm *wl_drm; 244 struct wl_shm *wl_shm; 245 struct wl_event_queue *wl_queue; 246 struct zwp_linux_dmabuf_v1 *wl_dmabuf; 247 struct u_vector *wl_modifiers; 248 bool authenticated; 249 BITSET_DECLARE(formats, EGL_DRI2_MAX_FORMATS); 250 uint32_t capabilities; 251 char *device_name; 252#endif 253 254#ifdef HAVE_ANDROID_PLATFORM 255 const gralloc_module_t *gralloc; 256 /* gralloc vendor usage bit for front rendering */ 257 uint32_t front_rendering_usage; 258#endif 259 260 bool is_render_node; 261 bool is_different_gpu; 262}; 263 264struct dri2_egl_context 265{ 266 _EGLContext base; 267 __DRIcontext *dri_context; 268}; 269 270#ifdef HAVE_WAYLAND_PLATFORM 271enum wayland_buffer_type { 272 WL_BUFFER_FRONT, 273 WL_BUFFER_BACK, 274 WL_BUFFER_THIRD, 275 WL_BUFFER_COUNT 276}; 277#endif 278 279struct dri2_egl_surface 280{ 281 _EGLSurface base; 282 __DRIdrawable *dri_drawable; 283 __DRIbuffer buffers[5]; 284 bool have_fake_front; 285 286#ifdef HAVE_X11_PLATFORM 287 xcb_drawable_t drawable; 288 xcb_xfixes_region_t region; 289 int depth; 290 int bytes_per_pixel; 291 xcb_gcontext_t gc; 292 xcb_gcontext_t swapgc; 293#endif 294 295#ifdef HAVE_WAYLAND_PLATFORM 296 struct wl_egl_window *wl_win; 297 int dx; 298 int dy; 299 struct wl_event_queue *wl_queue; 300 struct wl_surface *wl_surface_wrapper; 301 struct wl_display *wl_dpy_wrapper; 302 struct wl_drm *wl_drm_wrapper; 303 struct wl_callback *throttle_callback; 304 int format; 305 bool resized; 306#endif 307 308#ifdef HAVE_DRM_PLATFORM 309 struct gbm_dri_surface *gbm_surf; 310#endif 311 312 /* EGL-owned buffers */ 313 __DRIbuffer *local_buffers[__DRI_BUFFER_COUNT]; 314 315#if defined(HAVE_WAYLAND_PLATFORM) || defined(HAVE_DRM_PLATFORM) 316 struct { 317#ifdef HAVE_WAYLAND_PLATFORM 318 struct wl_buffer *wl_buffer; 319 bool wl_release; 320 __DRIimage *dri_image; 321 /* for is_different_gpu case. NULL else */ 322 __DRIimage *linear_copy; 323 /* for swrast */ 324 void *data; 325 int data_size; 326#endif 327#ifdef HAVE_DRM_PLATFORM 328 struct gbm_bo *bo; 329#endif 330 bool locked; 331 int age; 332 } color_buffers[4], *back, *current; 333#endif 334 335#ifdef HAVE_ANDROID_PLATFORM 336 struct ANativeWindow *window; 337 struct ANativeWindowBuffer *buffer; 338 __DRIimage *dri_image_back; 339 __DRIimage *dri_image_front; 340 341 /* Used to record all the buffers created by ANativeWindow and their ages. 342 * Allocate number of color_buffers based on query to android bufferqueue 343 * and save color_buffers_count. 344 */ 345 int color_buffers_count; 346 struct { 347 struct ANativeWindowBuffer *buffer; 348 int age; 349 } *color_buffers, *back; 350 uint32_t gralloc_usage; 351#endif 352 353 /* surfaceless and device */ 354 __DRIimage *front; 355 unsigned int visual; 356 357 int out_fence_fd; 358 EGLBoolean enable_out_fence; 359 360 /* swrast device */ 361 char *swrast_device_buffer; 362}; 363 364struct dri2_egl_config 365{ 366 _EGLConfig base; 367 const __DRIconfig *dri_config[2][2]; 368}; 369 370struct dri2_egl_image 371{ 372 _EGLImage base; 373 __DRIimage *dri_image; 374}; 375 376struct dri2_egl_sync { 377 _EGLSync base; 378 mtx_t mutex; 379 cnd_t cond; 380 int refcount; 381 void *fence; 382}; 383 384/* From driconf.h, user exposed so should be stable */ 385#define DRI_CONF_VBLANK_NEVER 0 386#define DRI_CONF_VBLANK_DEF_INTERVAL_0 1 387#define DRI_CONF_VBLANK_DEF_INTERVAL_1 2 388#define DRI_CONF_VBLANK_ALWAYS_SYNC 3 389 390/* standard typecasts */ 391_EGL_DRIVER_STANDARD_TYPECASTS(dri2_egl) 392_EGL_DRIVER_TYPECAST(dri2_egl_image, _EGLImage, obj) 393_EGL_DRIVER_TYPECAST(dri2_egl_sync, _EGLSync, obj) 394 395extern const __DRIimageLookupExtension image_lookup_extension; 396extern const __DRIuseInvalidateExtension use_invalidate; 397extern const __DRIbackgroundCallableExtension background_callable_extension; 398extern const __DRIswrastLoaderExtension swrast_pbuffer_loader_extension; 399 400EGLBoolean 401dri2_load_driver(_EGLDisplay *disp); 402 403/* Helper for platforms not using dri2_create_screen */ 404void 405dri2_setup_screen(_EGLDisplay *disp); 406 407void 408dri2_setup_swap_interval(_EGLDisplay *disp, int max_swap_interval); 409 410EGLBoolean 411dri2_load_driver_swrast(_EGLDisplay *disp); 412 413EGLBoolean 414dri2_load_driver_dri3(_EGLDisplay *disp); 415 416EGLBoolean 417dri2_create_screen(_EGLDisplay *disp); 418 419EGLBoolean 420dri2_setup_extensions(_EGLDisplay *disp); 421 422__DRIdrawable * 423dri2_surface_get_dri_drawable(_EGLSurface *surf); 424 425GLboolean 426dri2_validate_egl_image(void *image, void *data); 427 428__DRIimage * 429dri2_lookup_egl_image_validated(void *image, void *data); 430 431__DRIimage * 432dri2_lookup_egl_image(__DRIscreen *screen, void *image, void *data); 433 434void 435dri2_get_shifts_and_sizes(const __DRIcoreExtension *core, 436 const __DRIconfig *config, int *shifts, 437 unsigned int *sizes); 438 439void 440dri2_get_render_type_float(const __DRIcoreExtension *core, 441 const __DRIconfig *config, 442 bool *is_float); 443 444unsigned int 445dri2_image_format_for_pbuffer_config(struct dri2_egl_display *dri2_dpy, 446 const __DRIconfig *config); 447 448struct dri2_egl_config * 449dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id, 450 EGLint surface_type, const EGLint *attr_list, 451 const int *rgba_shifts, const unsigned int *rgba_sizes); 452 453EGLBoolean 454dri2_add_pbuffer_configs_for_visuals(_EGLDisplay *disp); 455 456_EGLImage * 457dri2_create_image_khr(_EGLDisplay *disp, _EGLContext *ctx, EGLenum target, 458 EGLClientBuffer buffer, const EGLint *attr_list); 459 460_EGLImage * 461dri2_create_image_dma_buf(_EGLDisplay *disp, _EGLContext *ctx, 462 EGLClientBuffer buffer, const EGLint *attr_list); 463 464_EGLImage * 465dri2_create_image_from_dri(_EGLDisplay *disp, __DRIimage *dri_image); 466 467#ifdef HAVE_X11_PLATFORM 468EGLBoolean 469dri2_initialize_x11(_EGLDisplay *disp); 470void 471dri2_teardown_x11(struct dri2_egl_display *dri2_dpy); 472unsigned int 473dri2_x11_get_red_mask_for_depth(struct dri2_egl_display *dri2_dpy, int depth); 474#else 475static inline EGLBoolean 476dri2_initialize_x11(_EGLDisplay *disp) 477{ 478 return _eglError(EGL_NOT_INITIALIZED, "X11 platform not built"); 479} 480static inline void 481dri2_teardown_x11(struct dri2_egl_display *dri2_dpy) {} 482static inline unsigned int 483dri2_x11_get_red_mask_for_depth(struct dri2_egl_display *dri2_dpy, int depth) 484{ 485 return 0; 486} 487#endif 488 489#ifdef HAVE_DRM_PLATFORM 490EGLBoolean 491dri2_initialize_drm(_EGLDisplay *disp); 492void 493dri2_teardown_drm(struct dri2_egl_display *dri2_dpy); 494#else 495static inline EGLBoolean 496dri2_initialize_drm(_EGLDisplay *disp) 497{ 498 return _eglError(EGL_NOT_INITIALIZED, "GBM/DRM platform not built"); 499} 500static inline void 501dri2_teardown_drm(struct dri2_egl_display *dri2_dpy) {} 502#endif 503 504#ifdef HAVE_WAYLAND_PLATFORM 505EGLBoolean 506dri2_initialize_wayland(_EGLDisplay *disp); 507void 508dri2_teardown_wayland(struct dri2_egl_display *dri2_dpy); 509bool 510dri2_wl_is_format_supported(void* user_data, uint32_t format); 511#else 512static inline EGLBoolean 513dri2_initialize_wayland(_EGLDisplay *disp) 514{ 515 return _eglError(EGL_NOT_INITIALIZED, "Wayland platform not built"); 516} 517static inline void 518dri2_teardown_wayland(struct dri2_egl_display *dri2_dpy) {} 519#endif 520 521#ifdef HAVE_ANDROID_PLATFORM 522EGLBoolean 523dri2_initialize_android(_EGLDisplay *disp); 524#else 525static inline EGLBoolean 526dri2_initialize_android(_EGLDisplay *disp) 527{ 528 return _eglError(EGL_NOT_INITIALIZED, "Android platform not built"); 529} 530#endif 531 532EGLBoolean 533dri2_initialize_surfaceless(_EGLDisplay *disp); 534 535EGLBoolean 536dri2_initialize_device(_EGLDisplay *disp); 537static inline void 538dri2_teardown_device(struct dri2_egl_display *dri2_dpy) { /* noop */ } 539 540void 541dri2_flush_drawable_for_swapbuffers(_EGLDisplay *disp, _EGLSurface *draw); 542 543const __DRIconfig * 544dri2_get_dri_config(struct dri2_egl_config *conf, EGLint surface_type, 545 EGLenum colorspace); 546 547static inline void 548dri2_set_WL_bind_wayland_display(_EGLDisplay *disp) 549{ 550#ifdef HAVE_WAYLAND_PLATFORM 551 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 552 553 if (dri2_dpy->device_name && dri2_dpy->image) { 554 if (dri2_dpy->image->base.version >= 10 && 555 dri2_dpy->image->getCapabilities != NULL) { 556 int capabilities; 557 558 capabilities = 559 dri2_dpy->image->getCapabilities(dri2_dpy->dri_screen); 560 disp->Extensions.WL_bind_wayland_display = 561 (capabilities & __DRI_IMAGE_CAP_GLOBAL_NAMES) != 0; 562 } else { 563 disp->Extensions.WL_bind_wayland_display = EGL_TRUE; 564 } 565 } 566#endif 567} 568 569void 570dri2_display_destroy(_EGLDisplay *disp); 571 572__DRIbuffer * 573dri2_egl_surface_alloc_local_buffer(struct dri2_egl_surface *dri2_surf, 574 unsigned int att, unsigned int format); 575 576void 577dri2_egl_surface_free_local_buffers(struct dri2_egl_surface *dri2_surf); 578 579EGLBoolean 580dri2_init_surface(_EGLSurface *surf, _EGLDisplay *disp, EGLint type, 581 _EGLConfig *conf, const EGLint *attrib_list, 582 EGLBoolean enable_out_fence, void *native_surface); 583 584void 585dri2_fini_surface(_EGLSurface *surf); 586 587EGLBoolean 588dri2_create_drawable(struct dri2_egl_display *dri2_dpy, 589 const __DRIconfig *config, 590 struct dri2_egl_surface *dri2_surf, 591 void *loaderPrivate); 592 593static inline uint64_t 594combine_u32_into_u64(uint32_t hi, uint32_t lo) 595{ 596 return (((uint64_t) hi) << 32) | (((uint64_t) lo) & 0xffffffff); 597} 598 599#endif /* EGL_DRI2_INCLUDED */ 600