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; 56struct zwp_linux_dmabuf_feedback_v1; 57#endif 58 59#include <GL/gl.h> 60#include <GL/internal/dri_interface.h> 61#include "kopper_interface.h" 62 63#ifdef HAVE_DRM_PLATFORM 64#include <gbm_driint.h> 65#endif 66 67#ifdef HAVE_ANDROID_PLATFORM 68#define LOG_TAG "EGL-DRI2" 69 70#include <hardware/gralloc.h> 71 72#if ANDROID_API_LEVEL >= 26 73#include <vndk/window.h> 74#else 75#include <system/window.h> 76#endif 77 78#ifdef HAVE_OHOS_PLATFORM 79#include "window.h" 80#endif 81 82#endif /* HAVE_ANDROID_PLATFORM */ 83 84#include "eglconfig.h" 85#include "eglcontext.h" 86#include "egldevice.h" 87#include "egldisplay.h" 88#include "egldriver.h" 89#include "eglcurrent.h" 90#include "egllog.h" 91#include "eglsurface.h" 92#include "eglimage.h" 93#include "eglsync.h" 94 95#include "util/u_vector.h" 96#include "util/u_dynarray.h" 97#include "util/bitset.h" 98 99struct wl_buffer; 100 101struct dri2_egl_display_vtbl { 102 /* mandatory on Wayland, unused otherwise */ 103 int (*authenticate)(_EGLDisplay *disp, uint32_t id); 104 105 /* mandatory */ 106 _EGLSurface* (*create_window_surface)(_EGLDisplay *disp, _EGLConfig *config, 107 void *native_window, 108 const EGLint *attrib_list); 109 110 /* optional */ 111 _EGLSurface* (*create_pixmap_surface)(_EGLDisplay *disp, _EGLConfig *config, 112 void *native_pixmap, 113 const EGLint *attrib_list); 114 115 /* optional */ 116 _EGLSurface* (*create_pbuffer_surface)(_EGLDisplay *disp, _EGLConfig *config, 117 const EGLint *attrib_list); 118 119 /* mandatory */ 120 EGLBoolean (*destroy_surface)(_EGLDisplay *disp, _EGLSurface *surface); 121 122 /* optional */ 123 EGLBoolean (*swap_interval)(_EGLDisplay *disp, _EGLSurface *surf, 124 EGLint interval); 125 126 /* mandatory */ 127 _EGLImage* (*create_image)(_EGLDisplay *disp, _EGLContext *ctx, 128 EGLenum target, EGLClientBuffer buffer, 129 const EGLint *attr_list); 130 131 /* mandatory */ 132 EGLBoolean (*swap_buffers)(_EGLDisplay *disp, _EGLSurface *surf); 133 134 /* optional - falls back to .swap_buffers */ 135 EGLBoolean (*swap_buffers_with_damage)(_EGLDisplay *disp, _EGLSurface *surface, 136 const EGLint *rects, EGLint n_rects); 137 138 /* optional */ 139 EGLBoolean (*swap_buffers_region)(_EGLDisplay *disp, _EGLSurface *surf, 140 EGLint numRects, const EGLint *rects); 141 142 /* optional */ 143 EGLBoolean (*post_sub_buffer)(_EGLDisplay *disp, _EGLSurface *surf, 144 EGLint x, EGLint y, 145 EGLint width, EGLint height); 146 147 /* optional */ 148 EGLBoolean (*copy_buffers)(_EGLDisplay *disp, _EGLSurface *surf, 149 void *native_pixmap_target); 150 151 /* optional */ 152 EGLint (*query_buffer_age)(_EGLDisplay *disp, _EGLSurface *surf); 153 154 /* optional */ 155 EGLBoolean (*query_surface)(_EGLDisplay *disp, _EGLSurface *surf, 156 EGLint attribute, EGLint *value); 157 158 /* optional */ 159 struct wl_buffer* (*create_wayland_buffer_from_image)(_EGLDisplay *disp, 160 _EGLImage *img); 161 162 /* optional */ 163 EGLBoolean (*get_sync_values)(_EGLDisplay *display, _EGLSurface *surface, 164 EGLuint64KHR *ust, EGLuint64KHR *msc, 165 EGLuint64KHR *sbc); 166 167 /* mandatory */ 168 __DRIdrawable *(*get_dri_drawable)(_EGLSurface *surf); 169 170 /* optional */ 171 void (*close_screen_notify)(_EGLDisplay *disp); 172 173 /* Used in EGL_KHR_mutable_render_buffer to update the native window's 174 * shared buffer mode. 175 * optional 176 */ 177 bool (*set_shared_buffer_mode)(_EGLDisplay *disp, _EGLSurface *surf, 178 bool mode); 179}; 180 181#ifdef HAVE_WAYLAND_PLATFORM 182struct dri2_wl_formats { 183 unsigned int num_formats; 184 185 /* Bitmap referencing dri2_wl_visuals */ 186 unsigned int *formats_bitmap; 187 188 /* Array of vectors. Contains one modifier vector per format */ 189 struct u_vector *modifiers; 190}; 191 192struct dmabuf_feedback_format_table { 193 unsigned int size; 194 struct { 195 uint32_t format; 196 uint32_t padding; /* unused */ 197 uint64_t modifier; 198 } *data; 199}; 200 201struct dmabuf_feedback_tranche { 202 dev_t target_device; 203 uint32_t flags; 204 struct dri2_wl_formats formats; 205}; 206 207struct dmabuf_feedback { 208 dev_t main_device; 209 struct dmabuf_feedback_format_table format_table; 210 struct util_dynarray tranches; 211 struct dmabuf_feedback_tranche pending_tranche; 212}; 213#endif 214 215struct dri2_egl_display 216{ 217 const struct dri2_egl_display_vtbl *vtbl; 218 219 int dri2_major; 220 int dri2_minor; 221 __DRIscreen *dri_screen; 222 bool own_dri_screen; 223 const __DRIconfig **driver_configs; 224 void *driver; 225 const __DRIcoreExtension *core; 226 const __DRIimageDriverExtension *image_driver; 227 const __DRIdri2Extension *dri2; 228 const __DRIswrastExtension *swrast; 229 const __DRIkopperExtension *kopper; 230 const __DRI2flushExtension *flush; 231 const __DRI2flushControlExtension *flush_control; 232 const __DRItexBufferExtension *tex_buffer; 233 const __DRIimageExtension *image; 234 const __DRIrobustnessExtension *robustness; 235 const __DRI2configQueryExtension *config; 236 const __DRI2fenceExtension *fence; 237 const __DRI2bufferDamageExtension *buffer_damage; 238 const __DRI2blobExtension *blob; 239 const __DRI2rendererQueryExtension *rendererQuery; 240 const __DRI2interopExtension *interop; 241 const __DRIconfigOptionsExtension *configOptions; 242 const __DRImutableRenderBufferDriverExtension *mutable_render_buffer; 243 int fd; 244 245 /* dri2_initialize/dri2_terminate increment/decrement this count, so does 246 * dri2_make_current (tracks if there are active contexts/surfaces). */ 247 int ref_count; 248 249 bool own_device; 250 bool invalidate_available; 251 int min_swap_interval; 252 int max_swap_interval; 253 int default_swap_interval; 254#ifdef HAVE_DRM_PLATFORM 255 struct gbm_dri_device *gbm_dri; 256#endif 257 258 char *driver_name; 259 260 const __DRIextension **loader_extensions; 261 const __DRIextension **driver_extensions; 262 263#ifdef HAVE_X11_PLATFORM 264 xcb_connection_t *conn; 265 xcb_screen_t *screen; 266 bool swap_available; 267#ifdef HAVE_DRI3 268 bool multibuffers_available; 269 int dri3_major_version; 270 int dri3_minor_version; 271 int present_major_version; 272 int present_minor_version; 273 struct loader_dri3_extensions loader_dri3_ext; 274#endif 275#endif 276 277#ifdef HAVE_WAYLAND_PLATFORM 278 struct wl_display *wl_dpy; 279 struct wl_display *wl_dpy_wrapper; 280 struct wl_registry *wl_registry; 281 struct wl_drm *wl_server_drm; 282 struct wl_drm *wl_drm; 283 uint32_t wl_drm_version, wl_drm_name; 284 struct wl_shm *wl_shm; 285 struct wl_event_queue *wl_queue; 286 struct zwp_linux_dmabuf_v1 *wl_dmabuf; 287 struct dri2_wl_formats formats; 288 struct zwp_linux_dmabuf_feedback_v1 *wl_dmabuf_feedback; 289 struct dmabuf_feedback_format_table format_table; 290 bool authenticated; 291 uint32_t capabilities; 292 char *device_name; 293#endif 294 295#ifdef HAVE_ANDROID_PLATFORM 296 const gralloc_module_t *gralloc; 297 /* gralloc vendor usage bit for front rendering */ 298 uint32_t front_rendering_usage; 299#endif 300 301 bool is_render_node; 302 bool is_different_gpu; 303}; 304 305struct dri2_egl_context 306{ 307 _EGLContext base; 308 __DRIcontext *dri_context; 309}; 310 311struct dri2_egl_surface 312{ 313 _EGLSurface base; 314 __DRIdrawable *dri_drawable; 315 __DRIbuffer buffers[5]; 316 bool have_fake_front; 317 318#ifdef HAVE_X11_PLATFORM 319 xcb_drawable_t drawable; 320 xcb_xfixes_region_t region; 321 int depth; 322 int bytes_per_pixel; 323 xcb_gcontext_t gc; 324 xcb_gcontext_t swapgc; 325#endif 326 327#ifdef HAVE_WAYLAND_PLATFORM 328 struct wl_egl_window *wl_win; 329 int dx; 330 int dy; 331 struct wl_event_queue *wl_queue; 332 struct wl_surface *wl_surface_wrapper; 333 struct wl_display *wl_dpy_wrapper; 334 struct wl_drm *wl_drm_wrapper; 335 struct wl_callback *throttle_callback; 336 struct zwp_linux_dmabuf_feedback_v1 *wl_dmabuf_feedback; 337 struct dmabuf_feedback dmabuf_feedback, pending_dmabuf_feedback; 338 bool compositor_using_another_device; 339 int format; 340 bool resized; 341 bool received_dmabuf_feedback; 342#endif 343 344#ifdef HAVE_DRM_PLATFORM 345 struct gbm_dri_surface *gbm_surf; 346#endif 347 348 /* EGL-owned buffers */ 349 __DRIbuffer *local_buffers[__DRI_BUFFER_COUNT]; 350 351#if defined(HAVE_WAYLAND_PLATFORM) || defined(HAVE_DRM_PLATFORM) 352 struct { 353#ifdef HAVE_WAYLAND_PLATFORM 354 struct wl_buffer *wl_buffer; 355 bool wl_release; 356 __DRIimage *dri_image; 357 /* for is_different_gpu case. NULL else */ 358 __DRIimage *linear_copy; 359 /* for swrast */ 360 void *data; 361 int data_size; 362#endif 363#ifdef HAVE_DRM_PLATFORM 364 struct gbm_bo *bo; 365#endif 366 bool locked; 367 int age; 368 } color_buffers[4], *back, *current; 369#endif 370 371#if defined(HAVE_ANDROID_PLATFORM) || defined (HAVE_OHOS_PLATFORM) 372 struct NativeWindow *window; 373 struct NativeWindowBuffer *buffer; 374 375 /* in-fence associated with buffer, -1 once passed down to dri layer: */ 376 int in_fence_fd; 377 378 __DRIimage *dri_image_back; 379 __DRIimage *dri_image_front; 380 381 /* Used to record all the buffers created by ANativeWindow and their ages. 382 * Allocate number of color_buffers based on query to android bufferqueue 383 * and save color_buffers_count. 384 */ 385 int color_buffers_count; 386 struct { 387 struct NativeWindowBuffer *buffer; 388 int age; 389 } *color_buffers, *back; 390 uint32_t gralloc_usage; 391#endif 392 393 /* surfaceless and device */ 394 __DRIimage *front; 395 unsigned int visual; 396 397 int out_fence_fd; 398 EGLBoolean enable_out_fence; 399 400 /* swrast device */ 401 char *swrast_device_buffer; 402}; 403 404struct dri2_egl_config 405{ 406 _EGLConfig base; 407 const __DRIconfig *dri_config[2][2]; 408}; 409 410struct dri2_egl_image 411{ 412 _EGLImage base; 413 __DRIimage *dri_image; 414}; 415 416struct dri2_egl_sync { 417 _EGLSync base; 418 mtx_t mutex; 419 cnd_t cond; 420 int refcount; 421 void *fence; 422}; 423 424/* standard typecasts */ 425_EGL_DRIVER_STANDARD_TYPECASTS(dri2_egl) 426_EGL_DRIVER_TYPECAST(dri2_egl_image, _EGLImage, obj) 427_EGL_DRIVER_TYPECAST(dri2_egl_sync, _EGLSync, obj) 428 429extern const __DRIimageLookupExtension image_lookup_extension; 430extern const __DRIuseInvalidateExtension use_invalidate; 431extern const __DRIbackgroundCallableExtension background_callable_extension; 432extern const __DRIswrastLoaderExtension swrast_pbuffer_loader_extension; 433 434EGLBoolean 435dri2_load_driver(_EGLDisplay *disp); 436 437/* Helper for platforms not using dri2_create_screen */ 438void 439dri2_setup_screen(_EGLDisplay *disp); 440 441void 442dri2_setup_swap_interval(_EGLDisplay *disp, int max_swap_interval); 443 444EGLBoolean 445dri2_load_driver_swrast(_EGLDisplay *disp); 446 447EGLBoolean 448dri2_load_driver_dri3(_EGLDisplay *disp); 449 450EGLBoolean 451dri2_create_screen(_EGLDisplay *disp); 452 453EGLBoolean 454dri2_setup_extensions(_EGLDisplay *disp); 455 456__DRIdrawable * 457dri2_surface_get_dri_drawable(_EGLSurface *surf); 458 459GLboolean 460dri2_validate_egl_image(void *image, void *data); 461 462__DRIimage * 463dri2_lookup_egl_image_validated(void *image, void *data); 464 465__DRIimage * 466dri2_lookup_egl_image(__DRIscreen *screen, void *image, void *data); 467 468void 469dri2_get_shifts_and_sizes(const __DRIcoreExtension *core, 470 const __DRIconfig *config, int *shifts, 471 unsigned int *sizes); 472 473void 474dri2_get_render_type_float(const __DRIcoreExtension *core, 475 const __DRIconfig *config, 476 bool *is_float); 477 478unsigned int 479dri2_image_format_for_pbuffer_config(struct dri2_egl_display *dri2_dpy, 480 const __DRIconfig *config); 481 482struct dri2_egl_config * 483dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id, 484 EGLint surface_type, const EGLint *attr_list, 485 const int *rgba_shifts, const unsigned int *rgba_sizes); 486 487EGLBoolean 488dri2_add_pbuffer_configs_for_visuals(_EGLDisplay *disp); 489 490_EGLImage * 491dri2_create_image_khr(_EGLDisplay *disp, _EGLContext *ctx, EGLenum target, 492 EGLClientBuffer buffer, const EGLint *attr_list); 493 494_EGLImage * 495dri2_create_image_dma_buf(_EGLDisplay *disp, _EGLContext *ctx, 496 EGLClientBuffer buffer, const EGLint *attr_list); 497 498_EGLImage * 499dri2_create_image_from_dri(_EGLDisplay *disp, __DRIimage *dri_image); 500 501#ifdef HAVE_X11_PLATFORM 502EGLBoolean 503dri2_initialize_x11(_EGLDisplay *disp); 504void 505dri2_teardown_x11(struct dri2_egl_display *dri2_dpy); 506unsigned int 507dri2_x11_get_red_mask_for_depth(struct dri2_egl_display *dri2_dpy, int depth); 508#else 509static inline EGLBoolean 510dri2_initialize_x11(_EGLDisplay *disp) 511{ 512 return _eglError(EGL_NOT_INITIALIZED, "X11 platform not built"); 513} 514static inline void 515dri2_teardown_x11(struct dri2_egl_display *dri2_dpy) {} 516static inline unsigned int 517dri2_x11_get_red_mask_for_depth(struct dri2_egl_display *dri2_dpy, int depth) 518{ 519 return 0; 520} 521#endif 522 523#ifdef HAVE_DRM_PLATFORM 524EGLBoolean 525dri2_initialize_drm(_EGLDisplay *disp); 526void 527dri2_teardown_drm(struct dri2_egl_display *dri2_dpy); 528#else 529static inline EGLBoolean 530dri2_initialize_drm(_EGLDisplay *disp) 531{ 532 return _eglError(EGL_NOT_INITIALIZED, "GBM/DRM platform not built"); 533} 534static inline void 535dri2_teardown_drm(struct dri2_egl_display *dri2_dpy) {} 536#endif 537 538#ifdef HAVE_WAYLAND_PLATFORM 539EGLBoolean 540dri2_initialize_wayland(_EGLDisplay *disp); 541void 542dri2_teardown_wayland(struct dri2_egl_display *dri2_dpy); 543bool 544dri2_wl_is_format_supported(void* user_data, uint32_t format); 545#else 546static inline EGLBoolean 547dri2_initialize_wayland(_EGLDisplay *disp) 548{ 549 return _eglError(EGL_NOT_INITIALIZED, "Wayland platform not built"); 550} 551static inline void 552dri2_teardown_wayland(struct dri2_egl_display *dri2_dpy) {} 553#endif 554 555#ifdef HAVE_ANDROID_PLATFORM 556EGLBoolean 557dri2_initialize_android(_EGLDisplay *disp); 558#else 559static inline EGLBoolean 560dri2_initialize_android(_EGLDisplay *disp) 561{ 562 return _eglError(EGL_NOT_INITIALIZED, "Android platform not built"); 563} 564#endif 565 566#ifdef HAVE_OHOS_PLATFORM 567EGLBoolean 568dri2_initialize_ohos(_EGLDisplay *disp); 569#else 570static inline EGLBoolean 571dri2_initialize_ohos(_EGLDisplay *disp) 572{ 573 return _eglError(EGL_NOT_INITIALIZED, "ohos platform not built"); 574} 575#endif 576 577EGLBoolean 578dri2_initialize_surfaceless(_EGLDisplay *disp); 579 580EGLBoolean 581dri2_initialize_device(_EGLDisplay *disp); 582static inline void 583dri2_teardown_device(struct dri2_egl_display *dri2_dpy) { /* noop */ } 584 585void 586dri2_flush_drawable_for_swapbuffers(_EGLDisplay *disp, _EGLSurface *draw); 587 588const __DRIconfig * 589dri2_get_dri_config(struct dri2_egl_config *conf, EGLint surface_type, 590 EGLenum colorspace); 591 592static inline void 593dri2_set_WL_bind_wayland_display(_EGLDisplay *disp) 594{ 595#ifdef HAVE_WAYLAND_PLATFORM 596 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 597 598 if (dri2_dpy->device_name && dri2_dpy->image) { 599 if (dri2_dpy->image->base.version >= 10 && 600 dri2_dpy->image->getCapabilities != NULL) { 601 int capabilities; 602 603 capabilities = 604 dri2_dpy->image->getCapabilities(dri2_dpy->dri_screen); 605 disp->Extensions.WL_bind_wayland_display = 606 (capabilities & __DRI_IMAGE_CAP_GLOBAL_NAMES) != 0; 607 } else { 608 disp->Extensions.WL_bind_wayland_display = EGL_TRUE; 609 } 610 } 611#endif 612} 613 614void 615dri2_display_destroy(_EGLDisplay *disp); 616 617__DRIbuffer * 618dri2_egl_surface_alloc_local_buffer(struct dri2_egl_surface *dri2_surf, 619 unsigned int att, unsigned int format); 620 621void 622dri2_egl_surface_free_local_buffers(struct dri2_egl_surface *dri2_surf); 623 624EGLBoolean 625dri2_init_surface(_EGLSurface *surf, _EGLDisplay *disp, EGLint type, 626 _EGLConfig *conf, const EGLint *attrib_list, 627 EGLBoolean enable_out_fence, void *native_surface); 628 629void 630dri2_fini_surface(_EGLSurface *surf); 631 632EGLBoolean 633dri2_create_drawable(struct dri2_egl_display *dri2_dpy, 634 const __DRIconfig *config, 635 struct dri2_egl_surface *dri2_surf, 636 void *loaderPrivate); 637 638static inline uint64_t 639combine_u32_into_u64(uint32_t hi, uint32_t lo) 640{ 641 return (((uint64_t) hi) << 32) | (((uint64_t) lo) & 0xffffffff); 642} 643 644#endif /* EGL_DRI2_INCLUDED */ 645