1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © 2011-2012 Intel Corporation 3bf215546Sopenharmony_ci * Copyright © 2012 Collabora, Ltd. 4bf215546Sopenharmony_ci * 5bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 6bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 7bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 8bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 10bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 11bf215546Sopenharmony_ci * 12bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 13bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 14bf215546Sopenharmony_ci * Software. 15bf215546Sopenharmony_ci * 16bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17bf215546Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19bf215546Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 20bf215546Sopenharmony_ci * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21bf215546Sopenharmony_ci * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23bf215546Sopenharmony_ci * DEALINGS IN THE SOFTWARE. 24bf215546Sopenharmony_ci * 25bf215546Sopenharmony_ci * Authors: 26bf215546Sopenharmony_ci * Kristian Høgsberg <krh@bitplanet.net> 27bf215546Sopenharmony_ci * Benjamin Franzke <benjaminfranzke@googlemail.com> 28bf215546Sopenharmony_ci */ 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_ci#include <stdint.h> 31bf215546Sopenharmony_ci#include <stdlib.h> 32bf215546Sopenharmony_ci#include <string.h> 33bf215546Sopenharmony_ci#include <limits.h> 34bf215546Sopenharmony_ci#include <dlfcn.h> 35bf215546Sopenharmony_ci#include <errno.h> 36bf215546Sopenharmony_ci#include <unistd.h> 37bf215546Sopenharmony_ci#include <fcntl.h> 38bf215546Sopenharmony_ci#include <xf86drm.h> 39bf215546Sopenharmony_ci#include "drm-uapi/drm_fourcc.h" 40bf215546Sopenharmony_ci#include <sys/mman.h> 41bf215546Sopenharmony_ci 42bf215546Sopenharmony_ci#include "egl_dri2.h" 43bf215546Sopenharmony_ci#include "loader_dri_helper.h" 44bf215546Sopenharmony_ci#include "loader.h" 45bf215546Sopenharmony_ci#include "util/u_vector.h" 46bf215546Sopenharmony_ci#include "util/anon_file.h" 47bf215546Sopenharmony_ci#include "eglglobals.h" 48bf215546Sopenharmony_ci#include "kopper_interface.h" 49bf215546Sopenharmony_ci 50bf215546Sopenharmony_ci#include <wayland-egl-backend.h> 51bf215546Sopenharmony_ci#include <wayland-client.h> 52bf215546Sopenharmony_ci#include "wayland-drm-client-protocol.h" 53bf215546Sopenharmony_ci#include "linux-dmabuf-unstable-v1-client-protocol.h" 54bf215546Sopenharmony_ci 55bf215546Sopenharmony_ci/* 56bf215546Sopenharmony_ci * The index of entries in this table is used as a bitmask in 57bf215546Sopenharmony_ci * dri2_dpy->formats.formats_bitmap, which tracks the formats supported 58bf215546Sopenharmony_ci * by our server. 59bf215546Sopenharmony_ci */ 60bf215546Sopenharmony_cistatic const struct dri2_wl_visual { 61bf215546Sopenharmony_ci const char *format_name; 62bf215546Sopenharmony_ci uint32_t wl_drm_format; 63bf215546Sopenharmony_ci uint32_t wl_shm_format; 64bf215546Sopenharmony_ci int dri_image_format; 65bf215546Sopenharmony_ci /* alt_dri_image_format is a substitute wl_buffer format to use for a 66bf215546Sopenharmony_ci * wl-server unsupported dri_image_format, ie. some other dri_image_format in 67bf215546Sopenharmony_ci * the table, of the same precision but with different channel ordering, or 68bf215546Sopenharmony_ci * __DRI_IMAGE_FORMAT_NONE if an alternate format is not needed or supported. 69bf215546Sopenharmony_ci * The code checks if alt_dri_image_format can be used as a fallback for a 70bf215546Sopenharmony_ci * dri_image_format for a given wl-server implementation. 71bf215546Sopenharmony_ci */ 72bf215546Sopenharmony_ci int alt_dri_image_format; 73bf215546Sopenharmony_ci int bpp; 74bf215546Sopenharmony_ci int rgba_shifts[4]; 75bf215546Sopenharmony_ci unsigned int rgba_sizes[4]; 76bf215546Sopenharmony_ci} dri2_wl_visuals[] = { 77bf215546Sopenharmony_ci { 78bf215546Sopenharmony_ci "ABGR16F", 79bf215546Sopenharmony_ci WL_DRM_FORMAT_ABGR16F, WL_SHM_FORMAT_ABGR16161616F, 80bf215546Sopenharmony_ci __DRI_IMAGE_FORMAT_ABGR16161616F, 0, 64, 81bf215546Sopenharmony_ci { 0, 16, 32, 48 }, 82bf215546Sopenharmony_ci { 16, 16, 16, 16 }, 83bf215546Sopenharmony_ci }, 84bf215546Sopenharmony_ci { 85bf215546Sopenharmony_ci "XBGR16F", 86bf215546Sopenharmony_ci WL_DRM_FORMAT_XBGR16F, WL_SHM_FORMAT_XBGR16161616F, 87bf215546Sopenharmony_ci __DRI_IMAGE_FORMAT_XBGR16161616F, 0, 64, 88bf215546Sopenharmony_ci { 0, 16, 32, -1 }, 89bf215546Sopenharmony_ci { 16, 16, 16, 0 }, 90bf215546Sopenharmony_ci }, 91bf215546Sopenharmony_ci { 92bf215546Sopenharmony_ci "XRGB2101010", 93bf215546Sopenharmony_ci WL_DRM_FORMAT_XRGB2101010, WL_SHM_FORMAT_XRGB2101010, 94bf215546Sopenharmony_ci __DRI_IMAGE_FORMAT_XRGB2101010, __DRI_IMAGE_FORMAT_XBGR2101010, 32, 95bf215546Sopenharmony_ci { 20, 10, 0, -1 }, 96bf215546Sopenharmony_ci { 10, 10, 10, 0 }, 97bf215546Sopenharmony_ci }, 98bf215546Sopenharmony_ci { 99bf215546Sopenharmony_ci "ARGB2101010", 100bf215546Sopenharmony_ci WL_DRM_FORMAT_ARGB2101010, WL_SHM_FORMAT_ARGB2101010, 101bf215546Sopenharmony_ci __DRI_IMAGE_FORMAT_ARGB2101010, __DRI_IMAGE_FORMAT_ABGR2101010, 32, 102bf215546Sopenharmony_ci { 20, 10, 0, 30 }, 103bf215546Sopenharmony_ci { 10, 10, 10, 2 }, 104bf215546Sopenharmony_ci }, 105bf215546Sopenharmony_ci { 106bf215546Sopenharmony_ci "XBGR2101010", 107bf215546Sopenharmony_ci WL_DRM_FORMAT_XBGR2101010, WL_SHM_FORMAT_XBGR2101010, 108bf215546Sopenharmony_ci __DRI_IMAGE_FORMAT_XBGR2101010, __DRI_IMAGE_FORMAT_XRGB2101010, 32, 109bf215546Sopenharmony_ci { 0, 10, 20, -1 }, 110bf215546Sopenharmony_ci { 10, 10, 10, 0 }, 111bf215546Sopenharmony_ci }, 112bf215546Sopenharmony_ci { 113bf215546Sopenharmony_ci "ABGR2101010", 114bf215546Sopenharmony_ci WL_DRM_FORMAT_ABGR2101010, WL_SHM_FORMAT_ABGR2101010, 115bf215546Sopenharmony_ci __DRI_IMAGE_FORMAT_ABGR2101010, __DRI_IMAGE_FORMAT_ARGB2101010, 32, 116bf215546Sopenharmony_ci { 0, 10, 20, 30 }, 117bf215546Sopenharmony_ci { 10, 10, 10, 2 }, 118bf215546Sopenharmony_ci }, 119bf215546Sopenharmony_ci { 120bf215546Sopenharmony_ci "XRGB8888", 121bf215546Sopenharmony_ci WL_DRM_FORMAT_XRGB8888, WL_SHM_FORMAT_XRGB8888, 122bf215546Sopenharmony_ci __DRI_IMAGE_FORMAT_XRGB8888, __DRI_IMAGE_FORMAT_NONE, 32, 123bf215546Sopenharmony_ci { 16, 8, 0, -1 }, 124bf215546Sopenharmony_ci { 8, 8, 8, 0 }, 125bf215546Sopenharmony_ci }, 126bf215546Sopenharmony_ci { 127bf215546Sopenharmony_ci "ARGB8888", 128bf215546Sopenharmony_ci WL_DRM_FORMAT_ARGB8888, WL_SHM_FORMAT_ARGB8888, 129bf215546Sopenharmony_ci __DRI_IMAGE_FORMAT_ARGB8888, __DRI_IMAGE_FORMAT_NONE, 32, 130bf215546Sopenharmony_ci { 16, 8, 0, 24 }, 131bf215546Sopenharmony_ci { 8, 8, 8, 8 }, 132bf215546Sopenharmony_ci }, 133bf215546Sopenharmony_ci { 134bf215546Sopenharmony_ci "ABGR8888", 135bf215546Sopenharmony_ci WL_DRM_FORMAT_ABGR8888, WL_SHM_FORMAT_ABGR8888, 136bf215546Sopenharmony_ci __DRI_IMAGE_FORMAT_ABGR8888, __DRI_IMAGE_FORMAT_NONE, 32, 137bf215546Sopenharmony_ci { 0, 8, 16, 24 }, 138bf215546Sopenharmony_ci { 8, 8, 8, 8 }, 139bf215546Sopenharmony_ci }, 140bf215546Sopenharmony_ci { 141bf215546Sopenharmony_ci "XBGR8888", 142bf215546Sopenharmony_ci WL_DRM_FORMAT_XBGR8888, WL_SHM_FORMAT_XBGR8888, 143bf215546Sopenharmony_ci __DRI_IMAGE_FORMAT_XBGR8888, __DRI_IMAGE_FORMAT_NONE, 32, 144bf215546Sopenharmony_ci { 0, 8, 16, -1 }, 145bf215546Sopenharmony_ci { 8, 8, 8, 0 }, 146bf215546Sopenharmony_ci }, 147bf215546Sopenharmony_ci { 148bf215546Sopenharmony_ci "RGB565", 149bf215546Sopenharmony_ci WL_DRM_FORMAT_RGB565, WL_SHM_FORMAT_RGB565, 150bf215546Sopenharmony_ci __DRI_IMAGE_FORMAT_RGB565, __DRI_IMAGE_FORMAT_NONE, 16, 151bf215546Sopenharmony_ci { 11, 5, 0, -1 }, 152bf215546Sopenharmony_ci { 5, 6, 5, 0 }, 153bf215546Sopenharmony_ci }, 154bf215546Sopenharmony_ci}; 155bf215546Sopenharmony_ci 156bf215546Sopenharmony_cistatic int 157bf215546Sopenharmony_cidri2_wl_visual_idx_from_config(struct dri2_egl_display *dri2_dpy, 158bf215546Sopenharmony_ci const __DRIconfig *config, 159bf215546Sopenharmony_ci bool force_opaque) 160bf215546Sopenharmony_ci{ 161bf215546Sopenharmony_ci int shifts[4]; 162bf215546Sopenharmony_ci unsigned int sizes[4]; 163bf215546Sopenharmony_ci 164bf215546Sopenharmony_ci dri2_get_shifts_and_sizes(dri2_dpy->core, config, shifts, sizes); 165bf215546Sopenharmony_ci 166bf215546Sopenharmony_ci for (unsigned int i = 0; i < ARRAY_SIZE(dri2_wl_visuals); i++) { 167bf215546Sopenharmony_ci const struct dri2_wl_visual *wl_visual = &dri2_wl_visuals[i]; 168bf215546Sopenharmony_ci 169bf215546Sopenharmony_ci int cmp_rgb_shifts = memcmp(shifts, wl_visual->rgba_shifts, 170bf215546Sopenharmony_ci 3 * sizeof(shifts[0])); 171bf215546Sopenharmony_ci int cmp_rgb_sizes = memcmp(sizes, wl_visual->rgba_sizes, 172bf215546Sopenharmony_ci 3 * sizeof(sizes[0])); 173bf215546Sopenharmony_ci 174bf215546Sopenharmony_ci if (cmp_rgb_shifts == 0 && cmp_rgb_sizes == 0 && 175bf215546Sopenharmony_ci wl_visual->rgba_shifts[3] == (force_opaque ? -1 : shifts[3]) && 176bf215546Sopenharmony_ci wl_visual->rgba_sizes[3] == (force_opaque ? 0 : sizes[3])) { 177bf215546Sopenharmony_ci return i; 178bf215546Sopenharmony_ci } 179bf215546Sopenharmony_ci } 180bf215546Sopenharmony_ci 181bf215546Sopenharmony_ci return -1; 182bf215546Sopenharmony_ci} 183bf215546Sopenharmony_ci 184bf215546Sopenharmony_cistatic int 185bf215546Sopenharmony_cidri2_wl_visual_idx_from_fourcc(uint32_t fourcc) 186bf215546Sopenharmony_ci{ 187bf215546Sopenharmony_ci for (int i = 0; i < ARRAY_SIZE(dri2_wl_visuals); i++) { 188bf215546Sopenharmony_ci /* wl_drm format codes overlap with DRIImage FourCC codes for all formats 189bf215546Sopenharmony_ci * we support. */ 190bf215546Sopenharmony_ci if (dri2_wl_visuals[i].wl_drm_format == fourcc) 191bf215546Sopenharmony_ci return i; 192bf215546Sopenharmony_ci } 193bf215546Sopenharmony_ci 194bf215546Sopenharmony_ci return -1; 195bf215546Sopenharmony_ci} 196bf215546Sopenharmony_ci 197bf215546Sopenharmony_cistatic int 198bf215546Sopenharmony_cidri2_wl_visual_idx_from_dri_image_format(uint32_t dri_image_format) 199bf215546Sopenharmony_ci{ 200bf215546Sopenharmony_ci for (int i = 0; i < ARRAY_SIZE(dri2_wl_visuals); i++) { 201bf215546Sopenharmony_ci if (dri2_wl_visuals[i].dri_image_format == dri_image_format) 202bf215546Sopenharmony_ci return i; 203bf215546Sopenharmony_ci } 204bf215546Sopenharmony_ci 205bf215546Sopenharmony_ci return -1; 206bf215546Sopenharmony_ci} 207bf215546Sopenharmony_ci 208bf215546Sopenharmony_cistatic int 209bf215546Sopenharmony_cidri2_wl_visual_idx_from_shm_format(uint32_t shm_format) 210bf215546Sopenharmony_ci{ 211bf215546Sopenharmony_ci for (int i = 0; i < ARRAY_SIZE(dri2_wl_visuals); i++) { 212bf215546Sopenharmony_ci if (dri2_wl_visuals[i].wl_shm_format == shm_format) 213bf215546Sopenharmony_ci return i; 214bf215546Sopenharmony_ci } 215bf215546Sopenharmony_ci 216bf215546Sopenharmony_ci return -1; 217bf215546Sopenharmony_ci} 218bf215546Sopenharmony_ci 219bf215546Sopenharmony_cibool 220bf215546Sopenharmony_cidri2_wl_is_format_supported(void* user_data, uint32_t format) 221bf215546Sopenharmony_ci{ 222bf215546Sopenharmony_ci _EGLDisplay *disp = (_EGLDisplay *) user_data; 223bf215546Sopenharmony_ci struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 224bf215546Sopenharmony_ci int j = dri2_wl_visual_idx_from_fourcc(format); 225bf215546Sopenharmony_ci 226bf215546Sopenharmony_ci if (j == -1) 227bf215546Sopenharmony_ci return false; 228bf215546Sopenharmony_ci 229bf215546Sopenharmony_ci for (int i = 0; dri2_dpy->driver_configs[i]; i++) 230bf215546Sopenharmony_ci if (j == dri2_wl_visual_idx_from_config(dri2_dpy, 231bf215546Sopenharmony_ci dri2_dpy->driver_configs[i], 232bf215546Sopenharmony_ci false)) 233bf215546Sopenharmony_ci return true; 234bf215546Sopenharmony_ci 235bf215546Sopenharmony_ci return false; 236bf215546Sopenharmony_ci} 237bf215546Sopenharmony_ci 238bf215546Sopenharmony_cistatic int 239bf215546Sopenharmony_ciroundtrip(struct dri2_egl_display *dri2_dpy) 240bf215546Sopenharmony_ci{ 241bf215546Sopenharmony_ci return wl_display_roundtrip_queue(dri2_dpy->wl_dpy, dri2_dpy->wl_queue); 242bf215546Sopenharmony_ci} 243bf215546Sopenharmony_ci 244bf215546Sopenharmony_cistatic void 245bf215546Sopenharmony_ciwl_buffer_release(void *data, struct wl_buffer *buffer) 246bf215546Sopenharmony_ci{ 247bf215546Sopenharmony_ci struct dri2_egl_surface *dri2_surf = data; 248bf215546Sopenharmony_ci int i; 249bf215546Sopenharmony_ci 250bf215546Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); ++i) 251bf215546Sopenharmony_ci if (dri2_surf->color_buffers[i].wl_buffer == buffer) 252bf215546Sopenharmony_ci break; 253bf215546Sopenharmony_ci 254bf215546Sopenharmony_ci assert (i < ARRAY_SIZE(dri2_surf->color_buffers)); 255bf215546Sopenharmony_ci 256bf215546Sopenharmony_ci if (dri2_surf->color_buffers[i].wl_release) { 257bf215546Sopenharmony_ci wl_buffer_destroy(buffer); 258bf215546Sopenharmony_ci dri2_surf->color_buffers[i].wl_release = false; 259bf215546Sopenharmony_ci dri2_surf->color_buffers[i].wl_buffer = NULL; 260bf215546Sopenharmony_ci dri2_surf->color_buffers[i].age = 0; 261bf215546Sopenharmony_ci } 262bf215546Sopenharmony_ci 263bf215546Sopenharmony_ci dri2_surf->color_buffers[i].locked = false; 264bf215546Sopenharmony_ci} 265bf215546Sopenharmony_ci 266bf215546Sopenharmony_cistatic const struct wl_buffer_listener wl_buffer_listener = { 267bf215546Sopenharmony_ci .release = wl_buffer_release 268bf215546Sopenharmony_ci}; 269bf215546Sopenharmony_ci 270bf215546Sopenharmony_cistatic void 271bf215546Sopenharmony_cidri2_wl_formats_fini(struct dri2_wl_formats *formats) 272bf215546Sopenharmony_ci{ 273bf215546Sopenharmony_ci unsigned int i; 274bf215546Sopenharmony_ci 275bf215546Sopenharmony_ci for (i = 0; i < formats->num_formats; i++) 276bf215546Sopenharmony_ci u_vector_finish(&formats->modifiers[i]); 277bf215546Sopenharmony_ci 278bf215546Sopenharmony_ci free(formats->modifiers); 279bf215546Sopenharmony_ci free(formats->formats_bitmap); 280bf215546Sopenharmony_ci} 281bf215546Sopenharmony_ci 282bf215546Sopenharmony_cistatic int 283bf215546Sopenharmony_cidri2_wl_formats_init(struct dri2_wl_formats *formats) 284bf215546Sopenharmony_ci{ 285bf215546Sopenharmony_ci unsigned int i, j; 286bf215546Sopenharmony_ci 287bf215546Sopenharmony_ci /* formats->formats_bitmap tells us if a format in dri2_wl_visuals is present 288bf215546Sopenharmony_ci * or not. So we must compute the amount of unsigned int's needed to 289bf215546Sopenharmony_ci * represent all the formats of dri2_wl_visuals. We use BITSET_WORDS for 290bf215546Sopenharmony_ci * this task. */ 291bf215546Sopenharmony_ci formats->num_formats = ARRAY_SIZE(dri2_wl_visuals); 292bf215546Sopenharmony_ci formats->formats_bitmap = calloc(BITSET_WORDS(formats->num_formats), 293bf215546Sopenharmony_ci sizeof(*formats->formats_bitmap)); 294bf215546Sopenharmony_ci if (!formats->formats_bitmap) 295bf215546Sopenharmony_ci goto err; 296bf215546Sopenharmony_ci 297bf215546Sopenharmony_ci /* Here we have an array of u_vector's to store the modifiers supported by 298bf215546Sopenharmony_ci * each format in the bitmask. */ 299bf215546Sopenharmony_ci formats->modifiers = calloc(formats->num_formats, 300bf215546Sopenharmony_ci sizeof(*formats->modifiers)); 301bf215546Sopenharmony_ci if (!formats->modifiers) 302bf215546Sopenharmony_ci goto err_modifier; 303bf215546Sopenharmony_ci 304bf215546Sopenharmony_ci for (i = 0; i < formats->num_formats; i++) 305bf215546Sopenharmony_ci if (!u_vector_init_pow2(&formats->modifiers[i], 4, sizeof(uint64_t))) { 306bf215546Sopenharmony_ci j = i; 307bf215546Sopenharmony_ci goto err_vector_init; 308bf215546Sopenharmony_ci } 309bf215546Sopenharmony_ci 310bf215546Sopenharmony_ci return 0; 311bf215546Sopenharmony_ci 312bf215546Sopenharmony_cierr_vector_init: 313bf215546Sopenharmony_ci for (i = 0; i < j; i++) 314bf215546Sopenharmony_ci u_vector_finish(&formats->modifiers[i]); 315bf215546Sopenharmony_ci free(formats->modifiers); 316bf215546Sopenharmony_cierr_modifier: 317bf215546Sopenharmony_ci free(formats->formats_bitmap); 318bf215546Sopenharmony_cierr: 319bf215546Sopenharmony_ci _eglError(EGL_BAD_ALLOC, "dri2_wl_formats_init"); 320bf215546Sopenharmony_ci return -1; 321bf215546Sopenharmony_ci} 322bf215546Sopenharmony_ci 323bf215546Sopenharmony_cistatic void 324bf215546Sopenharmony_cidmabuf_feedback_format_table_fini(struct dmabuf_feedback_format_table *format_table) 325bf215546Sopenharmony_ci{ 326bf215546Sopenharmony_ci if (format_table->data && format_table->data != MAP_FAILED) 327bf215546Sopenharmony_ci munmap(format_table->data, format_table->size); 328bf215546Sopenharmony_ci} 329bf215546Sopenharmony_ci 330bf215546Sopenharmony_cistatic void 331bf215546Sopenharmony_cidmabuf_feedback_format_table_init(struct dmabuf_feedback_format_table *format_table) 332bf215546Sopenharmony_ci{ 333bf215546Sopenharmony_ci memset(format_table, 0, sizeof(*format_table)); 334bf215546Sopenharmony_ci} 335bf215546Sopenharmony_ci 336bf215546Sopenharmony_cistatic void 337bf215546Sopenharmony_cidmabuf_feedback_tranche_fini(struct dmabuf_feedback_tranche *tranche) 338bf215546Sopenharmony_ci{ 339bf215546Sopenharmony_ci dri2_wl_formats_fini(&tranche->formats); 340bf215546Sopenharmony_ci} 341bf215546Sopenharmony_ci 342bf215546Sopenharmony_cistatic int 343bf215546Sopenharmony_cidmabuf_feedback_tranche_init(struct dmabuf_feedback_tranche *tranche) 344bf215546Sopenharmony_ci{ 345bf215546Sopenharmony_ci memset(tranche, 0, sizeof(*tranche)); 346bf215546Sopenharmony_ci 347bf215546Sopenharmony_ci if (dri2_wl_formats_init(&tranche->formats) < 0) 348bf215546Sopenharmony_ci return -1; 349bf215546Sopenharmony_ci 350bf215546Sopenharmony_ci return 0; 351bf215546Sopenharmony_ci} 352bf215546Sopenharmony_ci 353bf215546Sopenharmony_cistatic void 354bf215546Sopenharmony_cidmabuf_feedback_fini(struct dmabuf_feedback *dmabuf_feedback) 355bf215546Sopenharmony_ci{ 356bf215546Sopenharmony_ci dmabuf_feedback_tranche_fini(&dmabuf_feedback->pending_tranche); 357bf215546Sopenharmony_ci 358bf215546Sopenharmony_ci util_dynarray_foreach(&dmabuf_feedback->tranches, 359bf215546Sopenharmony_ci struct dmabuf_feedback_tranche, tranche) 360bf215546Sopenharmony_ci dmabuf_feedback_tranche_fini(tranche); 361bf215546Sopenharmony_ci util_dynarray_fini(&dmabuf_feedback->tranches); 362bf215546Sopenharmony_ci 363bf215546Sopenharmony_ci dmabuf_feedback_format_table_fini(&dmabuf_feedback->format_table); 364bf215546Sopenharmony_ci} 365bf215546Sopenharmony_ci 366bf215546Sopenharmony_cistatic int 367bf215546Sopenharmony_cidmabuf_feedback_init(struct dmabuf_feedback *dmabuf_feedback) 368bf215546Sopenharmony_ci{ 369bf215546Sopenharmony_ci memset(dmabuf_feedback, 0, sizeof(*dmabuf_feedback)); 370bf215546Sopenharmony_ci 371bf215546Sopenharmony_ci if (dmabuf_feedback_tranche_init(&dmabuf_feedback->pending_tranche) < 0) 372bf215546Sopenharmony_ci return -1; 373bf215546Sopenharmony_ci 374bf215546Sopenharmony_ci util_dynarray_init(&dmabuf_feedback->tranches, NULL); 375bf215546Sopenharmony_ci 376bf215546Sopenharmony_ci dmabuf_feedback_format_table_init(&dmabuf_feedback->format_table); 377bf215546Sopenharmony_ci 378bf215546Sopenharmony_ci return 0; 379bf215546Sopenharmony_ci} 380bf215546Sopenharmony_ci 381bf215546Sopenharmony_cistatic void 382bf215546Sopenharmony_ciresize_callback(struct wl_egl_window *wl_win, void *data) 383bf215546Sopenharmony_ci{ 384bf215546Sopenharmony_ci struct dri2_egl_surface *dri2_surf = data; 385bf215546Sopenharmony_ci struct dri2_egl_display *dri2_dpy = 386bf215546Sopenharmony_ci dri2_egl_display(dri2_surf->base.Resource.Display); 387bf215546Sopenharmony_ci 388bf215546Sopenharmony_ci if (dri2_surf->base.Width == wl_win->width && 389bf215546Sopenharmony_ci dri2_surf->base.Height == wl_win->height) 390bf215546Sopenharmony_ci return; 391bf215546Sopenharmony_ci 392bf215546Sopenharmony_ci dri2_surf->resized = true; 393bf215546Sopenharmony_ci 394bf215546Sopenharmony_ci /* Update the surface size as soon as native window is resized; from user 395bf215546Sopenharmony_ci * pov, this makes the effect that resize is done immediately after native 396bf215546Sopenharmony_ci * window resize, without requiring to wait until the first draw. 397bf215546Sopenharmony_ci * 398bf215546Sopenharmony_ci * A more detailed and lengthy explanation can be found at 399bf215546Sopenharmony_ci * https://lists.freedesktop.org/archives/mesa-dev/2018-June/196474.html 400bf215546Sopenharmony_ci */ 401bf215546Sopenharmony_ci if (!dri2_surf->back) { 402bf215546Sopenharmony_ci dri2_surf->base.Width = wl_win->width; 403bf215546Sopenharmony_ci dri2_surf->base.Height = wl_win->height; 404bf215546Sopenharmony_ci } 405bf215546Sopenharmony_ci dri2_dpy->flush->invalidate(dri2_surf->dri_drawable); 406bf215546Sopenharmony_ci} 407bf215546Sopenharmony_ci 408bf215546Sopenharmony_cistatic void 409bf215546Sopenharmony_cidestroy_window_callback(void *data) 410bf215546Sopenharmony_ci{ 411bf215546Sopenharmony_ci struct dri2_egl_surface *dri2_surf = data; 412bf215546Sopenharmony_ci dri2_surf->wl_win = NULL; 413bf215546Sopenharmony_ci} 414bf215546Sopenharmony_ci 415bf215546Sopenharmony_cistatic struct wl_surface * 416bf215546Sopenharmony_ciget_wl_surface_proxy(struct wl_egl_window *window) 417bf215546Sopenharmony_ci{ 418bf215546Sopenharmony_ci /* Version 3 of wl_egl_window introduced a version field at the same 419bf215546Sopenharmony_ci * location where a pointer to wl_surface was stored. Thus, if 420bf215546Sopenharmony_ci * window->version is dereferenceable, we've been given an older version of 421bf215546Sopenharmony_ci * wl_egl_window, and window->version points to wl_surface */ 422bf215546Sopenharmony_ci if (_eglPointerIsDereferencable((void *)(window->version))) { 423bf215546Sopenharmony_ci return wl_proxy_create_wrapper((void *)(window->version)); 424bf215546Sopenharmony_ci } 425bf215546Sopenharmony_ci return wl_proxy_create_wrapper(window->surface); 426bf215546Sopenharmony_ci} 427bf215546Sopenharmony_ci 428bf215546Sopenharmony_cistatic void 429bf215546Sopenharmony_cisurface_dmabuf_feedback_format_table(void *data, 430bf215546Sopenharmony_ci struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1, 431bf215546Sopenharmony_ci int32_t fd, uint32_t size) 432bf215546Sopenharmony_ci{ 433bf215546Sopenharmony_ci struct dri2_egl_surface *dri2_surf = data; 434bf215546Sopenharmony_ci struct dmabuf_feedback *feedback = &dri2_surf->pending_dmabuf_feedback; 435bf215546Sopenharmony_ci 436bf215546Sopenharmony_ci feedback->format_table.size = size; 437bf215546Sopenharmony_ci feedback->format_table.data = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); 438bf215546Sopenharmony_ci 439bf215546Sopenharmony_ci close(fd); 440bf215546Sopenharmony_ci} 441bf215546Sopenharmony_ci 442bf215546Sopenharmony_cistatic void 443bf215546Sopenharmony_cisurface_dmabuf_feedback_main_device(void *data, 444bf215546Sopenharmony_ci struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback, 445bf215546Sopenharmony_ci struct wl_array *device) 446bf215546Sopenharmony_ci{ 447bf215546Sopenharmony_ci struct dri2_egl_surface *dri2_surf = data; 448bf215546Sopenharmony_ci struct dmabuf_feedback *feedback = &dri2_surf->pending_dmabuf_feedback; 449bf215546Sopenharmony_ci 450bf215546Sopenharmony_ci memcpy(&feedback->main_device, device->data, sizeof(feedback->main_device)); 451bf215546Sopenharmony_ci 452bf215546Sopenharmony_ci /* Compositors may support switching render devices and change the main 453bf215546Sopenharmony_ci * device of the dma-buf feedback. In this case, when we reallocate the 454bf215546Sopenharmony_ci * buffers of the surface we must ensure that it is not allocated in memory 455bf215546Sopenharmony_ci * that is only visible to the GPU that EGL is using, as the compositor will 456bf215546Sopenharmony_ci * have to import them to the render device it is using. 457bf215546Sopenharmony_ci * 458bf215546Sopenharmony_ci * TODO: we still don't know how to allocate such buffers. 459bf215546Sopenharmony_ci */ 460bf215546Sopenharmony_ci if (dri2_surf->dmabuf_feedback.main_device != 0 && 461bf215546Sopenharmony_ci (feedback->main_device != dri2_surf->dmabuf_feedback.main_device)) 462bf215546Sopenharmony_ci dri2_surf->compositor_using_another_device = true; 463bf215546Sopenharmony_ci else 464bf215546Sopenharmony_ci dri2_surf->compositor_using_another_device = false; 465bf215546Sopenharmony_ci} 466bf215546Sopenharmony_ci 467bf215546Sopenharmony_cistatic void 468bf215546Sopenharmony_cisurface_dmabuf_feedback_tranche_target_device(void *data, 469bf215546Sopenharmony_ci struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback, 470bf215546Sopenharmony_ci struct wl_array *device) 471bf215546Sopenharmony_ci{ 472bf215546Sopenharmony_ci struct dri2_egl_surface *dri2_surf = data; 473bf215546Sopenharmony_ci struct dmabuf_feedback *feedback = &dri2_surf->pending_dmabuf_feedback; 474bf215546Sopenharmony_ci 475bf215546Sopenharmony_ci memcpy(&feedback->pending_tranche.target_device, device->data, 476bf215546Sopenharmony_ci sizeof(feedback->pending_tranche.target_device)); 477bf215546Sopenharmony_ci} 478bf215546Sopenharmony_ci 479bf215546Sopenharmony_cistatic void 480bf215546Sopenharmony_cisurface_dmabuf_feedback_tranche_flags(void *data, 481bf215546Sopenharmony_ci struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback, 482bf215546Sopenharmony_ci uint32_t flags) 483bf215546Sopenharmony_ci{ 484bf215546Sopenharmony_ci struct dri2_egl_surface *dri2_surf = data; 485bf215546Sopenharmony_ci struct dmabuf_feedback *feedback = &dri2_surf->pending_dmabuf_feedback; 486bf215546Sopenharmony_ci 487bf215546Sopenharmony_ci feedback->pending_tranche.flags = flags; 488bf215546Sopenharmony_ci} 489bf215546Sopenharmony_ci 490bf215546Sopenharmony_cistatic void 491bf215546Sopenharmony_cisurface_dmabuf_feedback_tranche_formats(void *data, 492bf215546Sopenharmony_ci struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback, 493bf215546Sopenharmony_ci struct wl_array *indices) 494bf215546Sopenharmony_ci{ 495bf215546Sopenharmony_ci struct dri2_egl_surface *dri2_surf = data; 496bf215546Sopenharmony_ci struct dmabuf_feedback *feedback = &dri2_surf->pending_dmabuf_feedback; 497bf215546Sopenharmony_ci uint64_t *modifier_ptr, modifier; 498bf215546Sopenharmony_ci uint32_t format; 499bf215546Sopenharmony_ci uint16_t *index; 500bf215546Sopenharmony_ci int visual_idx; 501bf215546Sopenharmony_ci 502bf215546Sopenharmony_ci /* Compositor may advertise or not a format table. If it does, we use it. 503bf215546Sopenharmony_ci * Otherwise, we steal the most recent advertised format table. If we don't have 504bf215546Sopenharmony_ci * a most recent advertised format table, compositor did something wrong. */ 505bf215546Sopenharmony_ci if (feedback->format_table.data == NULL) { 506bf215546Sopenharmony_ci feedback->format_table = dri2_surf->dmabuf_feedback.format_table; 507bf215546Sopenharmony_ci dmabuf_feedback_format_table_init(&dri2_surf->dmabuf_feedback.format_table); 508bf215546Sopenharmony_ci } 509bf215546Sopenharmony_ci if (feedback->format_table.data == MAP_FAILED) { 510bf215546Sopenharmony_ci _eglLog(_EGL_WARNING, "wayland-egl: we could not map the format table " 511bf215546Sopenharmony_ci "so we won't be able to use this batch of dma-buf " 512bf215546Sopenharmony_ci "feedback events."); 513bf215546Sopenharmony_ci return; 514bf215546Sopenharmony_ci } 515bf215546Sopenharmony_ci if (feedback->format_table.data == NULL) { 516bf215546Sopenharmony_ci _eglLog(_EGL_WARNING, "wayland-egl: compositor didn't advertise a format " 517bf215546Sopenharmony_ci "table, so we won't be able to use this batch of dma-buf " 518bf215546Sopenharmony_ci "feedback events."); 519bf215546Sopenharmony_ci return; 520bf215546Sopenharmony_ci } 521bf215546Sopenharmony_ci 522bf215546Sopenharmony_ci wl_array_for_each(index, indices) { 523bf215546Sopenharmony_ci format = feedback->format_table.data[*index].format; 524bf215546Sopenharmony_ci modifier = feedback->format_table.data[*index].modifier; 525bf215546Sopenharmony_ci 526bf215546Sopenharmony_ci /* Skip formats that are not the one the surface is already using. We 527bf215546Sopenharmony_ci * can't switch to another format. */ 528bf215546Sopenharmony_ci if (format != dri2_surf->format) 529bf215546Sopenharmony_ci continue; 530bf215546Sopenharmony_ci 531bf215546Sopenharmony_ci /* We are sure that the format is supported because of the check above. */ 532bf215546Sopenharmony_ci visual_idx = dri2_wl_visual_idx_from_fourcc(format); 533bf215546Sopenharmony_ci assert(visual_idx != -1); 534bf215546Sopenharmony_ci 535bf215546Sopenharmony_ci BITSET_SET(feedback->pending_tranche.formats.formats_bitmap, visual_idx); 536bf215546Sopenharmony_ci modifier_ptr = 537bf215546Sopenharmony_ci u_vector_add(&feedback->pending_tranche.formats.modifiers[visual_idx]); 538bf215546Sopenharmony_ci if (modifier_ptr) 539bf215546Sopenharmony_ci *modifier_ptr = modifier; 540bf215546Sopenharmony_ci } 541bf215546Sopenharmony_ci} 542bf215546Sopenharmony_ci 543bf215546Sopenharmony_cistatic void 544bf215546Sopenharmony_cisurface_dmabuf_feedback_tranche_done(void *data, 545bf215546Sopenharmony_ci struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback) 546bf215546Sopenharmony_ci{ 547bf215546Sopenharmony_ci struct dri2_egl_surface *dri2_surf = data; 548bf215546Sopenharmony_ci struct dmabuf_feedback *feedback = &dri2_surf->pending_dmabuf_feedback; 549bf215546Sopenharmony_ci 550bf215546Sopenharmony_ci /* Add tranche to array of tranches. */ 551bf215546Sopenharmony_ci util_dynarray_append(&feedback->tranches, struct dmabuf_feedback_tranche, 552bf215546Sopenharmony_ci feedback->pending_tranche); 553bf215546Sopenharmony_ci 554bf215546Sopenharmony_ci dmabuf_feedback_tranche_init(&feedback->pending_tranche); 555bf215546Sopenharmony_ci} 556bf215546Sopenharmony_ci 557bf215546Sopenharmony_cistatic void 558bf215546Sopenharmony_cisurface_dmabuf_feedback_done(void *data, 559bf215546Sopenharmony_ci struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback) 560bf215546Sopenharmony_ci{ 561bf215546Sopenharmony_ci struct dri2_egl_surface *dri2_surf = data; 562bf215546Sopenharmony_ci 563bf215546Sopenharmony_ci /* The dma-buf feedback protocol states that surface dma-buf feedback should 564bf215546Sopenharmony_ci * be sent by the compositor only if its buffers are using a suboptimal pair 565bf215546Sopenharmony_ci * of format and modifier. We can't change the buffer format, but we can 566bf215546Sopenharmony_ci * reallocate with another modifier. So we raise this flag in order to force 567bf215546Sopenharmony_ci * buffer reallocation based on the dma-buf feedback sent. */ 568bf215546Sopenharmony_ci dri2_surf->received_dmabuf_feedback = true; 569bf215546Sopenharmony_ci 570bf215546Sopenharmony_ci dmabuf_feedback_fini(&dri2_surf->dmabuf_feedback); 571bf215546Sopenharmony_ci dri2_surf->dmabuf_feedback = dri2_surf->pending_dmabuf_feedback; 572bf215546Sopenharmony_ci dmabuf_feedback_init(&dri2_surf->pending_dmabuf_feedback); 573bf215546Sopenharmony_ci} 574bf215546Sopenharmony_ci 575bf215546Sopenharmony_cistatic const struct zwp_linux_dmabuf_feedback_v1_listener 576bf215546Sopenharmony_cisurface_dmabuf_feedback_listener = { 577bf215546Sopenharmony_ci .format_table = surface_dmabuf_feedback_format_table, 578bf215546Sopenharmony_ci .main_device = surface_dmabuf_feedback_main_device, 579bf215546Sopenharmony_ci .tranche_target_device = surface_dmabuf_feedback_tranche_target_device, 580bf215546Sopenharmony_ci .tranche_flags = surface_dmabuf_feedback_tranche_flags, 581bf215546Sopenharmony_ci .tranche_formats = surface_dmabuf_feedback_tranche_formats, 582bf215546Sopenharmony_ci .tranche_done = surface_dmabuf_feedback_tranche_done, 583bf215546Sopenharmony_ci .done = surface_dmabuf_feedback_done, 584bf215546Sopenharmony_ci}; 585bf215546Sopenharmony_ci 586bf215546Sopenharmony_ci/** 587bf215546Sopenharmony_ci * Called via eglCreateWindowSurface(), drv->CreateWindowSurface(). 588bf215546Sopenharmony_ci */ 589bf215546Sopenharmony_cistatic _EGLSurface * 590bf215546Sopenharmony_cidri2_wl_create_window_surface(_EGLDisplay *disp, _EGLConfig *conf, 591bf215546Sopenharmony_ci void *native_window, const EGLint *attrib_list) 592bf215546Sopenharmony_ci{ 593bf215546Sopenharmony_ci struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 594bf215546Sopenharmony_ci struct dri2_egl_config *dri2_conf = dri2_egl_config(conf); 595bf215546Sopenharmony_ci struct wl_egl_window *window = native_window; 596bf215546Sopenharmony_ci struct dri2_egl_surface *dri2_surf; 597bf215546Sopenharmony_ci struct zwp_linux_dmabuf_v1 *dmabuf_wrapper; 598bf215546Sopenharmony_ci int visual_idx; 599bf215546Sopenharmony_ci const __DRIconfig *config; 600bf215546Sopenharmony_ci 601bf215546Sopenharmony_ci if (!window) { 602bf215546Sopenharmony_ci _eglError(EGL_BAD_NATIVE_WINDOW, "dri2_create_surface"); 603bf215546Sopenharmony_ci return NULL; 604bf215546Sopenharmony_ci } 605bf215546Sopenharmony_ci 606bf215546Sopenharmony_ci if (window->driver_private) { 607bf215546Sopenharmony_ci _eglError(EGL_BAD_ALLOC, "dri2_create_surface"); 608bf215546Sopenharmony_ci return NULL; 609bf215546Sopenharmony_ci } 610bf215546Sopenharmony_ci 611bf215546Sopenharmony_ci dri2_surf = calloc(1, sizeof *dri2_surf); 612bf215546Sopenharmony_ci if (!dri2_surf) { 613bf215546Sopenharmony_ci _eglError(EGL_BAD_ALLOC, "dri2_create_surface"); 614bf215546Sopenharmony_ci return NULL; 615bf215546Sopenharmony_ci } 616bf215546Sopenharmony_ci 617bf215546Sopenharmony_ci if (!dri2_init_surface(&dri2_surf->base, disp, EGL_WINDOW_BIT, conf, 618bf215546Sopenharmony_ci attrib_list, false, native_window)) 619bf215546Sopenharmony_ci goto cleanup_surf; 620bf215546Sopenharmony_ci 621bf215546Sopenharmony_ci config = dri2_get_dri_config(dri2_conf, EGL_WINDOW_BIT, 622bf215546Sopenharmony_ci dri2_surf->base.GLColorspace); 623bf215546Sopenharmony_ci 624bf215546Sopenharmony_ci if (!config) { 625bf215546Sopenharmony_ci _eglError(EGL_BAD_MATCH, "Unsupported surfacetype/colorspace configuration"); 626bf215546Sopenharmony_ci goto cleanup_surf; 627bf215546Sopenharmony_ci } 628bf215546Sopenharmony_ci 629bf215546Sopenharmony_ci dri2_surf->base.Width = window->width; 630bf215546Sopenharmony_ci dri2_surf->base.Height = window->height; 631bf215546Sopenharmony_ci 632bf215546Sopenharmony_ci#ifndef NDEBUG 633bf215546Sopenharmony_ci /* Enforce that every visual has an opaque variant (requirement to support 634bf215546Sopenharmony_ci * EGL_EXT_present_opaque) 635bf215546Sopenharmony_ci */ 636bf215546Sopenharmony_ci for (unsigned int i = 0; i < ARRAY_SIZE(dri2_wl_visuals); i++) { 637bf215546Sopenharmony_ci const struct dri2_wl_visual *transparent_visual = &dri2_wl_visuals[i]; 638bf215546Sopenharmony_ci if (transparent_visual->rgba_sizes[3] == 0) { 639bf215546Sopenharmony_ci continue; 640bf215546Sopenharmony_ci } 641bf215546Sopenharmony_ci 642bf215546Sopenharmony_ci bool found_opaque_equivalent = false; 643bf215546Sopenharmony_ci for (unsigned int j = 0; j < ARRAY_SIZE(dri2_wl_visuals); j++) { 644bf215546Sopenharmony_ci const struct dri2_wl_visual *opaque_visual = &dri2_wl_visuals[j]; 645bf215546Sopenharmony_ci if (opaque_visual->rgba_sizes[3] != 0) { 646bf215546Sopenharmony_ci continue; 647bf215546Sopenharmony_ci } 648bf215546Sopenharmony_ci 649bf215546Sopenharmony_ci int cmp_rgb_shifts = memcmp(transparent_visual->rgba_shifts, 650bf215546Sopenharmony_ci opaque_visual->rgba_shifts, 651bf215546Sopenharmony_ci 3 * sizeof(opaque_visual->rgba_shifts[0])); 652bf215546Sopenharmony_ci int cmp_rgb_sizes = memcmp(transparent_visual->rgba_sizes, 653bf215546Sopenharmony_ci opaque_visual->rgba_sizes, 654bf215546Sopenharmony_ci 3 * sizeof(opaque_visual->rgba_sizes[0])); 655bf215546Sopenharmony_ci 656bf215546Sopenharmony_ci if (cmp_rgb_shifts == 0 && cmp_rgb_sizes == 0) { 657bf215546Sopenharmony_ci found_opaque_equivalent = true; 658bf215546Sopenharmony_ci break; 659bf215546Sopenharmony_ci } 660bf215546Sopenharmony_ci } 661bf215546Sopenharmony_ci 662bf215546Sopenharmony_ci assert(found_opaque_equivalent); 663bf215546Sopenharmony_ci } 664bf215546Sopenharmony_ci#endif 665bf215546Sopenharmony_ci 666bf215546Sopenharmony_ci visual_idx = dri2_wl_visual_idx_from_config(dri2_dpy, config, 667bf215546Sopenharmony_ci dri2_surf->base.PresentOpaque); 668bf215546Sopenharmony_ci assert(visual_idx != -1); 669bf215546Sopenharmony_ci 670bf215546Sopenharmony_ci if (dri2_dpy->wl_dmabuf || dri2_dpy->wl_drm) { 671bf215546Sopenharmony_ci dri2_surf->format = dri2_wl_visuals[visual_idx].wl_drm_format; 672bf215546Sopenharmony_ci } else { 673bf215546Sopenharmony_ci assert(dri2_dpy->wl_shm); 674bf215546Sopenharmony_ci dri2_surf->format = dri2_wl_visuals[visual_idx].wl_shm_format; 675bf215546Sopenharmony_ci } 676bf215546Sopenharmony_ci 677bf215546Sopenharmony_ci dri2_surf->wl_queue = wl_display_create_queue(dri2_dpy->wl_dpy); 678bf215546Sopenharmony_ci if (!dri2_surf->wl_queue) { 679bf215546Sopenharmony_ci _eglError(EGL_BAD_ALLOC, "dri2_create_surface"); 680bf215546Sopenharmony_ci goto cleanup_surf; 681bf215546Sopenharmony_ci } 682bf215546Sopenharmony_ci 683bf215546Sopenharmony_ci if (dri2_dpy->wl_drm) { 684bf215546Sopenharmony_ci dri2_surf->wl_drm_wrapper = wl_proxy_create_wrapper(dri2_dpy->wl_drm); 685bf215546Sopenharmony_ci if (!dri2_surf->wl_drm_wrapper) { 686bf215546Sopenharmony_ci _eglError(EGL_BAD_ALLOC, "dri2_create_surface"); 687bf215546Sopenharmony_ci goto cleanup_queue; 688bf215546Sopenharmony_ci } 689bf215546Sopenharmony_ci wl_proxy_set_queue((struct wl_proxy *)dri2_surf->wl_drm_wrapper, 690bf215546Sopenharmony_ci dri2_surf->wl_queue); 691bf215546Sopenharmony_ci } 692bf215546Sopenharmony_ci 693bf215546Sopenharmony_ci dri2_surf->wl_dpy_wrapper = wl_proxy_create_wrapper(dri2_dpy->wl_dpy); 694bf215546Sopenharmony_ci if (!dri2_surf->wl_dpy_wrapper) { 695bf215546Sopenharmony_ci _eglError(EGL_BAD_ALLOC, "dri2_create_surface"); 696bf215546Sopenharmony_ci goto cleanup_drm; 697bf215546Sopenharmony_ci } 698bf215546Sopenharmony_ci wl_proxy_set_queue((struct wl_proxy *)dri2_surf->wl_dpy_wrapper, 699bf215546Sopenharmony_ci dri2_surf->wl_queue); 700bf215546Sopenharmony_ci 701bf215546Sopenharmony_ci dri2_surf->wl_surface_wrapper = get_wl_surface_proxy(window); 702bf215546Sopenharmony_ci if (!dri2_surf->wl_surface_wrapper) { 703bf215546Sopenharmony_ci _eglError(EGL_BAD_ALLOC, "dri2_create_surface"); 704bf215546Sopenharmony_ci goto cleanup_dpy_wrapper; 705bf215546Sopenharmony_ci } 706bf215546Sopenharmony_ci wl_proxy_set_queue((struct wl_proxy *)dri2_surf->wl_surface_wrapper, 707bf215546Sopenharmony_ci dri2_surf->wl_queue); 708bf215546Sopenharmony_ci 709bf215546Sopenharmony_ci if (dri2_dpy->wl_dmabuf && zwp_linux_dmabuf_v1_get_version(dri2_dpy->wl_dmabuf) >= 710bf215546Sopenharmony_ci ZWP_LINUX_DMABUF_V1_GET_SURFACE_FEEDBACK_SINCE_VERSION) { 711bf215546Sopenharmony_ci dmabuf_wrapper = wl_proxy_create_wrapper(dri2_dpy->wl_dmabuf); 712bf215546Sopenharmony_ci if (!dmabuf_wrapper) { 713bf215546Sopenharmony_ci _eglError(EGL_BAD_ALLOC, "dri2_create_surface"); 714bf215546Sopenharmony_ci goto cleanup_surf_wrapper; 715bf215546Sopenharmony_ci } 716bf215546Sopenharmony_ci wl_proxy_set_queue((struct wl_proxy *)dmabuf_wrapper, 717bf215546Sopenharmony_ci dri2_surf->wl_queue); 718bf215546Sopenharmony_ci dri2_surf->wl_dmabuf_feedback = 719bf215546Sopenharmony_ci zwp_linux_dmabuf_v1_get_surface_feedback(dmabuf_wrapper, 720bf215546Sopenharmony_ci dri2_surf->wl_surface_wrapper); 721bf215546Sopenharmony_ci wl_proxy_wrapper_destroy(dmabuf_wrapper); 722bf215546Sopenharmony_ci 723bf215546Sopenharmony_ci zwp_linux_dmabuf_feedback_v1_add_listener(dri2_surf->wl_dmabuf_feedback, 724bf215546Sopenharmony_ci &surface_dmabuf_feedback_listener, 725bf215546Sopenharmony_ci dri2_surf); 726bf215546Sopenharmony_ci 727bf215546Sopenharmony_ci if (dmabuf_feedback_init(&dri2_surf->pending_dmabuf_feedback) < 0) { 728bf215546Sopenharmony_ci zwp_linux_dmabuf_feedback_v1_destroy(dri2_surf->wl_dmabuf_feedback); 729bf215546Sopenharmony_ci goto cleanup_surf_wrapper; 730bf215546Sopenharmony_ci } 731bf215546Sopenharmony_ci if (dmabuf_feedback_init(&dri2_surf->dmabuf_feedback) < 0) { 732bf215546Sopenharmony_ci dmabuf_feedback_fini(&dri2_surf->pending_dmabuf_feedback); 733bf215546Sopenharmony_ci zwp_linux_dmabuf_feedback_v1_destroy(dri2_surf->wl_dmabuf_feedback); 734bf215546Sopenharmony_ci goto cleanup_surf_wrapper; 735bf215546Sopenharmony_ci } 736bf215546Sopenharmony_ci 737bf215546Sopenharmony_ci if (roundtrip(dri2_dpy) < 0) 738bf215546Sopenharmony_ci goto cleanup_dmabuf_feedback; 739bf215546Sopenharmony_ci } 740bf215546Sopenharmony_ci 741bf215546Sopenharmony_ci dri2_surf->wl_win = window; 742bf215546Sopenharmony_ci dri2_surf->wl_win->driver_private = dri2_surf; 743bf215546Sopenharmony_ci dri2_surf->wl_win->destroy_window_callback = destroy_window_callback; 744bf215546Sopenharmony_ci if (dri2_dpy->flush) 745bf215546Sopenharmony_ci dri2_surf->wl_win->resize_callback = resize_callback; 746bf215546Sopenharmony_ci 747bf215546Sopenharmony_ci if (!dri2_create_drawable(dri2_dpy, config, dri2_surf, dri2_surf)) 748bf215546Sopenharmony_ci goto cleanup_dmabuf_feedback; 749bf215546Sopenharmony_ci 750bf215546Sopenharmony_ci dri2_surf->base.SwapInterval = dri2_dpy->default_swap_interval; 751bf215546Sopenharmony_ci 752bf215546Sopenharmony_ci return &dri2_surf->base; 753bf215546Sopenharmony_ci 754bf215546Sopenharmony_ci cleanup_dmabuf_feedback: 755bf215546Sopenharmony_ci if (dri2_surf->wl_dmabuf_feedback) { 756bf215546Sopenharmony_ci zwp_linux_dmabuf_feedback_v1_destroy(dri2_surf->wl_dmabuf_feedback); 757bf215546Sopenharmony_ci dmabuf_feedback_fini(&dri2_surf->dmabuf_feedback); 758bf215546Sopenharmony_ci dmabuf_feedback_fini(&dri2_surf->pending_dmabuf_feedback); 759bf215546Sopenharmony_ci } 760bf215546Sopenharmony_ci cleanup_surf_wrapper: 761bf215546Sopenharmony_ci wl_proxy_wrapper_destroy(dri2_surf->wl_surface_wrapper); 762bf215546Sopenharmony_ci cleanup_dpy_wrapper: 763bf215546Sopenharmony_ci wl_proxy_wrapper_destroy(dri2_surf->wl_dpy_wrapper); 764bf215546Sopenharmony_ci cleanup_drm: 765bf215546Sopenharmony_ci if (dri2_surf->wl_drm_wrapper) 766bf215546Sopenharmony_ci wl_proxy_wrapper_destroy(dri2_surf->wl_drm_wrapper); 767bf215546Sopenharmony_ci cleanup_queue: 768bf215546Sopenharmony_ci wl_event_queue_destroy(dri2_surf->wl_queue); 769bf215546Sopenharmony_ci cleanup_surf: 770bf215546Sopenharmony_ci free(dri2_surf); 771bf215546Sopenharmony_ci 772bf215546Sopenharmony_ci return NULL; 773bf215546Sopenharmony_ci} 774bf215546Sopenharmony_ci 775bf215546Sopenharmony_cistatic _EGLSurface * 776bf215546Sopenharmony_cidri2_wl_create_pixmap_surface(_EGLDisplay *disp, _EGLConfig *conf, 777bf215546Sopenharmony_ci void *native_window, const EGLint *attrib_list) 778bf215546Sopenharmony_ci{ 779bf215546Sopenharmony_ci /* From the EGL_EXT_platform_wayland spec, version 3: 780bf215546Sopenharmony_ci * 781bf215546Sopenharmony_ci * It is not valid to call eglCreatePlatformPixmapSurfaceEXT with a <dpy> 782bf215546Sopenharmony_ci * that belongs to Wayland. Any such call fails and generates 783bf215546Sopenharmony_ci * EGL_BAD_PARAMETER. 784bf215546Sopenharmony_ci */ 785bf215546Sopenharmony_ci _eglError(EGL_BAD_PARAMETER, "cannot create EGL pixmap surfaces on " 786bf215546Sopenharmony_ci "Wayland"); 787bf215546Sopenharmony_ci return NULL; 788bf215546Sopenharmony_ci} 789bf215546Sopenharmony_ci 790bf215546Sopenharmony_ci/** 791bf215546Sopenharmony_ci * Called via eglDestroySurface(), drv->DestroySurface(). 792bf215546Sopenharmony_ci */ 793bf215546Sopenharmony_cistatic EGLBoolean 794bf215546Sopenharmony_cidri2_wl_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf) 795bf215546Sopenharmony_ci{ 796bf215546Sopenharmony_ci struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 797bf215546Sopenharmony_ci struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); 798bf215546Sopenharmony_ci 799bf215546Sopenharmony_ci dri2_dpy->core->destroyDrawable(dri2_surf->dri_drawable); 800bf215546Sopenharmony_ci 801bf215546Sopenharmony_ci for (int i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) { 802bf215546Sopenharmony_ci if (dri2_surf->color_buffers[i].wl_buffer) 803bf215546Sopenharmony_ci wl_buffer_destroy(dri2_surf->color_buffers[i].wl_buffer); 804bf215546Sopenharmony_ci if (dri2_surf->color_buffers[i].dri_image) 805bf215546Sopenharmony_ci dri2_dpy->image->destroyImage(dri2_surf->color_buffers[i].dri_image); 806bf215546Sopenharmony_ci if (dri2_surf->color_buffers[i].linear_copy) 807bf215546Sopenharmony_ci dri2_dpy->image->destroyImage(dri2_surf->color_buffers[i].linear_copy); 808bf215546Sopenharmony_ci if (dri2_surf->color_buffers[i].data) 809bf215546Sopenharmony_ci munmap(dri2_surf->color_buffers[i].data, 810bf215546Sopenharmony_ci dri2_surf->color_buffers[i].data_size); 811bf215546Sopenharmony_ci } 812bf215546Sopenharmony_ci 813bf215546Sopenharmony_ci if (dri2_dpy->dri2) 814bf215546Sopenharmony_ci dri2_egl_surface_free_local_buffers(dri2_surf); 815bf215546Sopenharmony_ci 816bf215546Sopenharmony_ci if (dri2_surf->throttle_callback) 817bf215546Sopenharmony_ci wl_callback_destroy(dri2_surf->throttle_callback); 818bf215546Sopenharmony_ci 819bf215546Sopenharmony_ci if (dri2_surf->wl_win) { 820bf215546Sopenharmony_ci dri2_surf->wl_win->driver_private = NULL; 821bf215546Sopenharmony_ci dri2_surf->wl_win->resize_callback = NULL; 822bf215546Sopenharmony_ci dri2_surf->wl_win->destroy_window_callback = NULL; 823bf215546Sopenharmony_ci } 824bf215546Sopenharmony_ci 825bf215546Sopenharmony_ci wl_proxy_wrapper_destroy(dri2_surf->wl_surface_wrapper); 826bf215546Sopenharmony_ci wl_proxy_wrapper_destroy(dri2_surf->wl_dpy_wrapper); 827bf215546Sopenharmony_ci if (dri2_surf->wl_drm_wrapper) 828bf215546Sopenharmony_ci wl_proxy_wrapper_destroy(dri2_surf->wl_drm_wrapper); 829bf215546Sopenharmony_ci if (dri2_surf->wl_dmabuf_feedback) { 830bf215546Sopenharmony_ci zwp_linux_dmabuf_feedback_v1_destroy(dri2_surf->wl_dmabuf_feedback); 831bf215546Sopenharmony_ci dmabuf_feedback_fini(&dri2_surf->dmabuf_feedback); 832bf215546Sopenharmony_ci dmabuf_feedback_fini(&dri2_surf->pending_dmabuf_feedback); 833bf215546Sopenharmony_ci } 834bf215546Sopenharmony_ci wl_event_queue_destroy(dri2_surf->wl_queue); 835bf215546Sopenharmony_ci 836bf215546Sopenharmony_ci dri2_fini_surface(surf); 837bf215546Sopenharmony_ci free(surf); 838bf215546Sopenharmony_ci 839bf215546Sopenharmony_ci return EGL_TRUE; 840bf215546Sopenharmony_ci} 841bf215546Sopenharmony_ci 842bf215546Sopenharmony_cistatic EGLBoolean 843bf215546Sopenharmony_cidri2_wl_swap_interval(_EGLDisplay *disp, _EGLSurface *surf, EGLint interval) 844bf215546Sopenharmony_ci{ 845bf215546Sopenharmony_ci struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 846bf215546Sopenharmony_ci struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); 847bf215546Sopenharmony_ci 848bf215546Sopenharmony_ci if (dri2_dpy->kopper) 849bf215546Sopenharmony_ci dri2_dpy->kopper->setSwapInterval(dri2_surf->dri_drawable, interval); 850bf215546Sopenharmony_ci 851bf215546Sopenharmony_ci return EGL_TRUE; 852bf215546Sopenharmony_ci} 853bf215546Sopenharmony_ci 854bf215546Sopenharmony_cistatic void 855bf215546Sopenharmony_cidri2_wl_release_buffers(struct dri2_egl_surface *dri2_surf) 856bf215546Sopenharmony_ci{ 857bf215546Sopenharmony_ci struct dri2_egl_display *dri2_dpy = 858bf215546Sopenharmony_ci dri2_egl_display(dri2_surf->base.Resource.Display); 859bf215546Sopenharmony_ci 860bf215546Sopenharmony_ci for (int i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) { 861bf215546Sopenharmony_ci if (dri2_surf->color_buffers[i].wl_buffer) { 862bf215546Sopenharmony_ci if (dri2_surf->color_buffers[i].locked) { 863bf215546Sopenharmony_ci dri2_surf->color_buffers[i].wl_release = true; 864bf215546Sopenharmony_ci } else { 865bf215546Sopenharmony_ci wl_buffer_destroy(dri2_surf->color_buffers[i].wl_buffer); 866bf215546Sopenharmony_ci dri2_surf->color_buffers[i].wl_buffer = NULL; 867bf215546Sopenharmony_ci } 868bf215546Sopenharmony_ci } 869bf215546Sopenharmony_ci if (dri2_surf->color_buffers[i].dri_image) 870bf215546Sopenharmony_ci dri2_dpy->image->destroyImage(dri2_surf->color_buffers[i].dri_image); 871bf215546Sopenharmony_ci if (dri2_surf->color_buffers[i].linear_copy) 872bf215546Sopenharmony_ci dri2_dpy->image->destroyImage(dri2_surf->color_buffers[i].linear_copy); 873bf215546Sopenharmony_ci if (dri2_surf->color_buffers[i].data) 874bf215546Sopenharmony_ci munmap(dri2_surf->color_buffers[i].data, 875bf215546Sopenharmony_ci dri2_surf->color_buffers[i].data_size); 876bf215546Sopenharmony_ci 877bf215546Sopenharmony_ci dri2_surf->color_buffers[i].dri_image = NULL; 878bf215546Sopenharmony_ci dri2_surf->color_buffers[i].linear_copy = NULL; 879bf215546Sopenharmony_ci dri2_surf->color_buffers[i].data = NULL; 880bf215546Sopenharmony_ci dri2_surf->color_buffers[i].age = 0; 881bf215546Sopenharmony_ci } 882bf215546Sopenharmony_ci 883bf215546Sopenharmony_ci if (dri2_dpy->dri2) 884bf215546Sopenharmony_ci dri2_egl_surface_free_local_buffers(dri2_surf); 885bf215546Sopenharmony_ci} 886bf215546Sopenharmony_ci 887bf215546Sopenharmony_cistatic void 888bf215546Sopenharmony_cicreate_dri_image_diff_gpu(struct dri2_egl_surface *dri2_surf, 889bf215546Sopenharmony_ci unsigned int linear_dri_image_format, uint32_t use_flags) 890bf215546Sopenharmony_ci{ 891bf215546Sopenharmony_ci struct dri2_egl_display *dri2_dpy = 892bf215546Sopenharmony_ci dri2_egl_display(dri2_surf->base.Resource.Display); 893bf215546Sopenharmony_ci uint64_t linear_mod; 894bf215546Sopenharmony_ci 895bf215546Sopenharmony_ci /* The LINEAR modifier should be a perfect alias of the LINEAR use flag */ 896bf215546Sopenharmony_ci linear_mod = DRM_FORMAT_MOD_LINEAR; 897bf215546Sopenharmony_ci 898bf215546Sopenharmony_ci dri2_surf->back->linear_copy = 899bf215546Sopenharmony_ci loader_dri_create_image(dri2_dpy->dri_screen, dri2_dpy->image, 900bf215546Sopenharmony_ci dri2_surf->base.Width, 901bf215546Sopenharmony_ci dri2_surf->base.Height, 902bf215546Sopenharmony_ci linear_dri_image_format, 903bf215546Sopenharmony_ci use_flags | __DRI_IMAGE_USE_LINEAR, 904bf215546Sopenharmony_ci &linear_mod, 1, NULL); 905bf215546Sopenharmony_ci} 906bf215546Sopenharmony_ci 907bf215546Sopenharmony_cistatic void 908bf215546Sopenharmony_cicreate_dri_image_from_dmabuf_feedback(struct dri2_egl_surface *dri2_surf, 909bf215546Sopenharmony_ci unsigned int dri_image_format, uint32_t use_flags) 910bf215546Sopenharmony_ci{ 911bf215546Sopenharmony_ci struct dri2_egl_display *dri2_dpy = 912bf215546Sopenharmony_ci dri2_egl_display(dri2_surf->base.Resource.Display); 913bf215546Sopenharmony_ci int visual_idx; 914bf215546Sopenharmony_ci uint64_t *modifiers; 915bf215546Sopenharmony_ci unsigned int num_modifiers; 916bf215546Sopenharmony_ci uint32_t flags; 917bf215546Sopenharmony_ci 918bf215546Sopenharmony_ci /* We don't have valid dma-buf feedback, so return */ 919bf215546Sopenharmony_ci if (dri2_surf->dmabuf_feedback.main_device == 0) 920bf215546Sopenharmony_ci return; 921bf215546Sopenharmony_ci 922bf215546Sopenharmony_ci visual_idx = dri2_wl_visual_idx_from_fourcc(dri2_surf->format); 923bf215546Sopenharmony_ci assert(visual_idx != -1); 924bf215546Sopenharmony_ci 925bf215546Sopenharmony_ci /* Iterates through the dma-buf feedback to pick a new set of modifiers. The 926bf215546Sopenharmony_ci * tranches are sent in descending order of preference by the compositor, so 927bf215546Sopenharmony_ci * the first set that we can pick is the best one. For now we still can't 928bf215546Sopenharmony_ci * specify the target device in order to make the render device try its best 929bf215546Sopenharmony_ci * to allocate memory that can be directly scanned out by the KMS device. But 930bf215546Sopenharmony_ci * in the future this may change (newer versions of 931bf215546Sopenharmony_ci * createImageWithModifiers). Also, we are safe to pick modifiers from 932bf215546Sopenharmony_ci * tranches whose target device differs from the main device, as compositors 933bf215546Sopenharmony_ci * do not expose (in dma-buf feedback tranches) formats/modifiers that are 934bf215546Sopenharmony_ci * incompatible with the main device. */ 935bf215546Sopenharmony_ci util_dynarray_foreach(&dri2_surf->dmabuf_feedback.tranches, 936bf215546Sopenharmony_ci struct dmabuf_feedback_tranche, tranche) { 937bf215546Sopenharmony_ci /* Ignore tranches that do not contain dri2_surf->format */ 938bf215546Sopenharmony_ci if (!BITSET_TEST(tranche->formats.formats_bitmap, visual_idx)) 939bf215546Sopenharmony_ci continue; 940bf215546Sopenharmony_ci modifiers = u_vector_tail(&tranche->formats.modifiers[visual_idx]); 941bf215546Sopenharmony_ci num_modifiers = u_vector_length(&tranche->formats.modifiers[visual_idx]); 942bf215546Sopenharmony_ci 943bf215546Sopenharmony_ci /* For the purposes of this function, an INVALID modifier on 944bf215546Sopenharmony_ci * its own means the modifiers aren't supported. */ 945bf215546Sopenharmony_ci if (num_modifiers == 0 || 946bf215546Sopenharmony_ci (num_modifiers == 1 && modifiers[0] == DRM_FORMAT_MOD_INVALID)) { 947bf215546Sopenharmony_ci num_modifiers = 0; 948bf215546Sopenharmony_ci modifiers = NULL; 949bf215546Sopenharmony_ci } 950bf215546Sopenharmony_ci 951bf215546Sopenharmony_ci flags = use_flags; 952bf215546Sopenharmony_ci if (tranche->flags & ZWP_LINUX_DMABUF_FEEDBACK_V1_TRANCHE_FLAGS_SCANOUT) 953bf215546Sopenharmony_ci flags |= __DRI_IMAGE_USE_SCANOUT; 954bf215546Sopenharmony_ci 955bf215546Sopenharmony_ci dri2_surf->back->dri_image = 956bf215546Sopenharmony_ci loader_dri_create_image(dri2_dpy->dri_screen, dri2_dpy->image, 957bf215546Sopenharmony_ci dri2_surf->base.Width, 958bf215546Sopenharmony_ci dri2_surf->base.Height, 959bf215546Sopenharmony_ci dri_image_format, 960bf215546Sopenharmony_ci dri2_dpy->is_different_gpu ? 0 : flags, 961bf215546Sopenharmony_ci modifiers, num_modifiers, NULL); 962bf215546Sopenharmony_ci 963bf215546Sopenharmony_ci if (dri2_surf->back->dri_image) 964bf215546Sopenharmony_ci return; 965bf215546Sopenharmony_ci } 966bf215546Sopenharmony_ci} 967bf215546Sopenharmony_ci 968bf215546Sopenharmony_cistatic void 969bf215546Sopenharmony_cicreate_dri_image(struct dri2_egl_surface *dri2_surf, 970bf215546Sopenharmony_ci unsigned int dri_image_format, uint32_t use_flags) 971bf215546Sopenharmony_ci{ 972bf215546Sopenharmony_ci struct dri2_egl_display *dri2_dpy = 973bf215546Sopenharmony_ci dri2_egl_display(dri2_surf->base.Resource.Display); 974bf215546Sopenharmony_ci int visual_idx; 975bf215546Sopenharmony_ci uint64_t *modifiers; 976bf215546Sopenharmony_ci unsigned int num_modifiers; 977bf215546Sopenharmony_ci 978bf215546Sopenharmony_ci visual_idx = dri2_wl_visual_idx_from_fourcc(dri2_surf->format); 979bf215546Sopenharmony_ci modifiers = u_vector_tail(&dri2_dpy->formats.modifiers[visual_idx]); 980bf215546Sopenharmony_ci num_modifiers = u_vector_length(&dri2_dpy->formats.modifiers[visual_idx]); 981bf215546Sopenharmony_ci 982bf215546Sopenharmony_ci /* For the purposes of this function, an INVALID modifier on 983bf215546Sopenharmony_ci * its own means the modifiers aren't supported. */ 984bf215546Sopenharmony_ci if (num_modifiers == 0 || 985bf215546Sopenharmony_ci (num_modifiers == 1 && modifiers[0] == DRM_FORMAT_MOD_INVALID)) { 986bf215546Sopenharmony_ci num_modifiers = 0; 987bf215546Sopenharmony_ci modifiers = NULL; 988bf215546Sopenharmony_ci } 989bf215546Sopenharmony_ci 990bf215546Sopenharmony_ci /* If our DRIImage implementation does not support createImageWithModifiers, 991bf215546Sopenharmony_ci * then fall back to the old createImage, and hope it allocates an image 992bf215546Sopenharmony_ci * which is acceptable to the winsys. */ 993bf215546Sopenharmony_ci dri2_surf->back->dri_image = 994bf215546Sopenharmony_ci loader_dri_create_image(dri2_dpy->dri_screen, dri2_dpy->image, 995bf215546Sopenharmony_ci dri2_surf->base.Width, 996bf215546Sopenharmony_ci dri2_surf->base.Height, 997bf215546Sopenharmony_ci dri_image_format, 998bf215546Sopenharmony_ci dri2_dpy->is_different_gpu ? 0 : use_flags, 999bf215546Sopenharmony_ci modifiers, num_modifiers, NULL); 1000bf215546Sopenharmony_ci} 1001bf215546Sopenharmony_ci 1002bf215546Sopenharmony_cistatic int 1003bf215546Sopenharmony_ciget_back_bo(struct dri2_egl_surface *dri2_surf) 1004bf215546Sopenharmony_ci{ 1005bf215546Sopenharmony_ci struct dri2_egl_display *dri2_dpy = 1006bf215546Sopenharmony_ci dri2_egl_display(dri2_surf->base.Resource.Display); 1007bf215546Sopenharmony_ci int use_flags; 1008bf215546Sopenharmony_ci int visual_idx; 1009bf215546Sopenharmony_ci unsigned int dri_image_format; 1010bf215546Sopenharmony_ci unsigned int linear_dri_image_format; 1011bf215546Sopenharmony_ci 1012bf215546Sopenharmony_ci visual_idx = dri2_wl_visual_idx_from_fourcc(dri2_surf->format); 1013bf215546Sopenharmony_ci assert(visual_idx != -1); 1014bf215546Sopenharmony_ci dri_image_format = dri2_wl_visuals[visual_idx].dri_image_format; 1015bf215546Sopenharmony_ci linear_dri_image_format = dri_image_format; 1016bf215546Sopenharmony_ci 1017bf215546Sopenharmony_ci /* Substitute dri image format if server does not support original format */ 1018bf215546Sopenharmony_ci if (!BITSET_TEST(dri2_dpy->formats.formats_bitmap, visual_idx)) 1019bf215546Sopenharmony_ci linear_dri_image_format = dri2_wl_visuals[visual_idx].alt_dri_image_format; 1020bf215546Sopenharmony_ci 1021bf215546Sopenharmony_ci /* These asserts hold, as long as dri2_wl_visuals[] is self-consistent and 1022bf215546Sopenharmony_ci * the PRIME substitution logic in dri2_wl_add_configs_for_visuals() is free 1023bf215546Sopenharmony_ci * of bugs. 1024bf215546Sopenharmony_ci */ 1025bf215546Sopenharmony_ci assert(linear_dri_image_format != __DRI_IMAGE_FORMAT_NONE); 1026bf215546Sopenharmony_ci assert(BITSET_TEST(dri2_dpy->formats.formats_bitmap, 1027bf215546Sopenharmony_ci dri2_wl_visual_idx_from_dri_image_format(linear_dri_image_format))); 1028bf215546Sopenharmony_ci 1029bf215546Sopenharmony_ci /* There might be a buffer release already queued that wasn't processed */ 1030bf215546Sopenharmony_ci wl_display_dispatch_queue_pending(dri2_dpy->wl_dpy, dri2_surf->wl_queue); 1031bf215546Sopenharmony_ci 1032bf215546Sopenharmony_ci while (dri2_surf->back == NULL) { 1033bf215546Sopenharmony_ci for (int i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) { 1034bf215546Sopenharmony_ci /* Get an unlocked buffer, preferably one with a dri_buffer 1035bf215546Sopenharmony_ci * already allocated. */ 1036bf215546Sopenharmony_ci if (dri2_surf->color_buffers[i].locked) 1037bf215546Sopenharmony_ci continue; 1038bf215546Sopenharmony_ci if (dri2_surf->back == NULL) 1039bf215546Sopenharmony_ci dri2_surf->back = &dri2_surf->color_buffers[i]; 1040bf215546Sopenharmony_ci else if (dri2_surf->back->dri_image == NULL) 1041bf215546Sopenharmony_ci dri2_surf->back = &dri2_surf->color_buffers[i]; 1042bf215546Sopenharmony_ci } 1043bf215546Sopenharmony_ci 1044bf215546Sopenharmony_ci if (dri2_surf->back) 1045bf215546Sopenharmony_ci break; 1046bf215546Sopenharmony_ci 1047bf215546Sopenharmony_ci /* If we don't have a buffer, then block on the server to release one for 1048bf215546Sopenharmony_ci * us, and try again. wl_display_dispatch_queue will process any pending 1049bf215546Sopenharmony_ci * events, however not all servers flush on issuing a buffer release 1050bf215546Sopenharmony_ci * event. So, we spam the server with roundtrips as they always cause a 1051bf215546Sopenharmony_ci * client flush. 1052bf215546Sopenharmony_ci */ 1053bf215546Sopenharmony_ci if (wl_display_roundtrip_queue(dri2_dpy->wl_dpy, 1054bf215546Sopenharmony_ci dri2_surf->wl_queue) < 0) 1055bf215546Sopenharmony_ci return -1; 1056bf215546Sopenharmony_ci } 1057bf215546Sopenharmony_ci 1058bf215546Sopenharmony_ci if (dri2_surf->back == NULL) 1059bf215546Sopenharmony_ci return -1; 1060bf215546Sopenharmony_ci 1061bf215546Sopenharmony_ci use_flags = __DRI_IMAGE_USE_SHARE | __DRI_IMAGE_USE_BACKBUFFER; 1062bf215546Sopenharmony_ci 1063bf215546Sopenharmony_ci if (dri2_surf->base.ProtectedContent) { 1064bf215546Sopenharmony_ci /* Protected buffers can't be read from another GPU */ 1065bf215546Sopenharmony_ci if (dri2_dpy->is_different_gpu) 1066bf215546Sopenharmony_ci return -1; 1067bf215546Sopenharmony_ci use_flags |= __DRI_IMAGE_USE_PROTECTED; 1068bf215546Sopenharmony_ci } 1069bf215546Sopenharmony_ci 1070bf215546Sopenharmony_ci if (dri2_dpy->is_different_gpu && dri2_surf->back->linear_copy == NULL) { 1071bf215546Sopenharmony_ci create_dri_image_diff_gpu(dri2_surf, linear_dri_image_format, use_flags); 1072bf215546Sopenharmony_ci if (dri2_surf->back->linear_copy == NULL) 1073bf215546Sopenharmony_ci return -1; 1074bf215546Sopenharmony_ci } 1075bf215546Sopenharmony_ci 1076bf215546Sopenharmony_ci if (dri2_surf->back->dri_image == NULL) { 1077bf215546Sopenharmony_ci if (dri2_surf->wl_dmabuf_feedback) 1078bf215546Sopenharmony_ci create_dri_image_from_dmabuf_feedback(dri2_surf, dri_image_format, use_flags); 1079bf215546Sopenharmony_ci if (dri2_surf->back->dri_image == NULL) 1080bf215546Sopenharmony_ci create_dri_image(dri2_surf, dri_image_format, use_flags); 1081bf215546Sopenharmony_ci dri2_surf->back->age = 0; 1082bf215546Sopenharmony_ci } 1083bf215546Sopenharmony_ci 1084bf215546Sopenharmony_ci if (dri2_surf->back->dri_image == NULL) 1085bf215546Sopenharmony_ci return -1; 1086bf215546Sopenharmony_ci 1087bf215546Sopenharmony_ci dri2_surf->back->locked = true; 1088bf215546Sopenharmony_ci 1089bf215546Sopenharmony_ci return 0; 1090bf215546Sopenharmony_ci} 1091bf215546Sopenharmony_ci 1092bf215546Sopenharmony_ci 1093bf215546Sopenharmony_cistatic void 1094bf215546Sopenharmony_ciback_bo_to_dri_buffer(struct dri2_egl_surface *dri2_surf, __DRIbuffer *buffer) 1095bf215546Sopenharmony_ci{ 1096bf215546Sopenharmony_ci struct dri2_egl_display *dri2_dpy = 1097bf215546Sopenharmony_ci dri2_egl_display(dri2_surf->base.Resource.Display); 1098bf215546Sopenharmony_ci __DRIimage *image; 1099bf215546Sopenharmony_ci int name, pitch; 1100bf215546Sopenharmony_ci 1101bf215546Sopenharmony_ci image = dri2_surf->back->dri_image; 1102bf215546Sopenharmony_ci 1103bf215546Sopenharmony_ci dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_NAME, &name); 1104bf215546Sopenharmony_ci dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_STRIDE, &pitch); 1105bf215546Sopenharmony_ci 1106bf215546Sopenharmony_ci buffer->attachment = __DRI_BUFFER_BACK_LEFT; 1107bf215546Sopenharmony_ci buffer->name = name; 1108bf215546Sopenharmony_ci buffer->pitch = pitch; 1109bf215546Sopenharmony_ci buffer->cpp = 4; 1110bf215546Sopenharmony_ci buffer->flags = 0; 1111bf215546Sopenharmony_ci} 1112bf215546Sopenharmony_ci 1113bf215546Sopenharmony_ci/* Value chosen empirically as a compromise between avoiding frequent 1114bf215546Sopenharmony_ci * reallocations and extended time of increased memory consumption due to 1115bf215546Sopenharmony_ci * unused buffers being kept. 1116bf215546Sopenharmony_ci */ 1117bf215546Sopenharmony_ci#define BUFFER_TRIM_AGE_HYSTERESIS 20 1118bf215546Sopenharmony_ci 1119bf215546Sopenharmony_cistatic int 1120bf215546Sopenharmony_ciupdate_buffers(struct dri2_egl_surface *dri2_surf) 1121bf215546Sopenharmony_ci{ 1122bf215546Sopenharmony_ci struct dri2_egl_display *dri2_dpy = 1123bf215546Sopenharmony_ci dri2_egl_display(dri2_surf->base.Resource.Display); 1124bf215546Sopenharmony_ci 1125bf215546Sopenharmony_ci if (dri2_surf->wl_win && 1126bf215546Sopenharmony_ci (dri2_surf->base.Width != dri2_surf->wl_win->width || 1127bf215546Sopenharmony_ci dri2_surf->base.Height != dri2_surf->wl_win->height)) { 1128bf215546Sopenharmony_ci 1129bf215546Sopenharmony_ci dri2_surf->base.Width = dri2_surf->wl_win->width; 1130bf215546Sopenharmony_ci dri2_surf->base.Height = dri2_surf->wl_win->height; 1131bf215546Sopenharmony_ci dri2_surf->dx = dri2_surf->wl_win->dx; 1132bf215546Sopenharmony_ci dri2_surf->dy = dri2_surf->wl_win->dy; 1133bf215546Sopenharmony_ci } 1134bf215546Sopenharmony_ci 1135bf215546Sopenharmony_ci if (dri2_surf->resized || dri2_surf->received_dmabuf_feedback) { 1136bf215546Sopenharmony_ci dri2_wl_release_buffers(dri2_surf); 1137bf215546Sopenharmony_ci dri2_surf->resized = false; 1138bf215546Sopenharmony_ci dri2_surf->received_dmabuf_feedback = false; 1139bf215546Sopenharmony_ci } 1140bf215546Sopenharmony_ci 1141bf215546Sopenharmony_ci if (get_back_bo(dri2_surf) < 0) { 1142bf215546Sopenharmony_ci _eglError(EGL_BAD_ALLOC, "failed to allocate color buffer"); 1143bf215546Sopenharmony_ci return -1; 1144bf215546Sopenharmony_ci } 1145bf215546Sopenharmony_ci 1146bf215546Sopenharmony_ci /* If we have an extra unlocked buffer at this point, we had to do triple 1147bf215546Sopenharmony_ci * buffering for a while, but now can go back to just double buffering. 1148bf215546Sopenharmony_ci * That means we can free any unlocked buffer now. To avoid toggling between 1149bf215546Sopenharmony_ci * going back to double buffering and needing to allocate another buffer too 1150bf215546Sopenharmony_ci * fast we let the unneeded buffer sit around for a short while. */ 1151bf215546Sopenharmony_ci for (int i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) { 1152bf215546Sopenharmony_ci if (!dri2_surf->color_buffers[i].locked && 1153bf215546Sopenharmony_ci dri2_surf->color_buffers[i].wl_buffer && 1154bf215546Sopenharmony_ci dri2_surf->color_buffers[i].age > BUFFER_TRIM_AGE_HYSTERESIS) { 1155bf215546Sopenharmony_ci wl_buffer_destroy(dri2_surf->color_buffers[i].wl_buffer); 1156bf215546Sopenharmony_ci dri2_dpy->image->destroyImage(dri2_surf->color_buffers[i].dri_image); 1157bf215546Sopenharmony_ci if (dri2_dpy->is_different_gpu) 1158bf215546Sopenharmony_ci dri2_dpy->image->destroyImage(dri2_surf->color_buffers[i].linear_copy); 1159bf215546Sopenharmony_ci dri2_surf->color_buffers[i].wl_buffer = NULL; 1160bf215546Sopenharmony_ci dri2_surf->color_buffers[i].dri_image = NULL; 1161bf215546Sopenharmony_ci dri2_surf->color_buffers[i].linear_copy = NULL; 1162bf215546Sopenharmony_ci dri2_surf->color_buffers[i].age = 0; 1163bf215546Sopenharmony_ci } 1164bf215546Sopenharmony_ci } 1165bf215546Sopenharmony_ci 1166bf215546Sopenharmony_ci return 0; 1167bf215546Sopenharmony_ci} 1168bf215546Sopenharmony_ci 1169bf215546Sopenharmony_cistatic int 1170bf215546Sopenharmony_ciupdate_buffers_if_needed(struct dri2_egl_surface *dri2_surf) 1171bf215546Sopenharmony_ci{ 1172bf215546Sopenharmony_ci if (dri2_surf->back != NULL) 1173bf215546Sopenharmony_ci return 0; 1174bf215546Sopenharmony_ci 1175bf215546Sopenharmony_ci return update_buffers(dri2_surf); 1176bf215546Sopenharmony_ci} 1177bf215546Sopenharmony_ci 1178bf215546Sopenharmony_cistatic __DRIbuffer * 1179bf215546Sopenharmony_cidri2_wl_get_buffers_with_format(__DRIdrawable * driDrawable, 1180bf215546Sopenharmony_ci int *width, int *height, 1181bf215546Sopenharmony_ci unsigned int *attachments, int count, 1182bf215546Sopenharmony_ci int *out_count, void *loaderPrivate) 1183bf215546Sopenharmony_ci{ 1184bf215546Sopenharmony_ci struct dri2_egl_surface *dri2_surf = loaderPrivate; 1185bf215546Sopenharmony_ci int i, j; 1186bf215546Sopenharmony_ci 1187bf215546Sopenharmony_ci if (update_buffers_if_needed(dri2_surf) < 0) 1188bf215546Sopenharmony_ci return NULL; 1189bf215546Sopenharmony_ci 1190bf215546Sopenharmony_ci for (i = 0, j = 0; i < 2 * count; i += 2, j++) { 1191bf215546Sopenharmony_ci __DRIbuffer *local; 1192bf215546Sopenharmony_ci 1193bf215546Sopenharmony_ci switch (attachments[i]) { 1194bf215546Sopenharmony_ci case __DRI_BUFFER_BACK_LEFT: 1195bf215546Sopenharmony_ci back_bo_to_dri_buffer(dri2_surf, &dri2_surf->buffers[j]); 1196bf215546Sopenharmony_ci break; 1197bf215546Sopenharmony_ci default: 1198bf215546Sopenharmony_ci local = dri2_egl_surface_alloc_local_buffer(dri2_surf, attachments[i], 1199bf215546Sopenharmony_ci attachments[i + 1]); 1200bf215546Sopenharmony_ci 1201bf215546Sopenharmony_ci if (!local) { 1202bf215546Sopenharmony_ci _eglError(EGL_BAD_ALLOC, "failed to allocate local buffer"); 1203bf215546Sopenharmony_ci return NULL; 1204bf215546Sopenharmony_ci } 1205bf215546Sopenharmony_ci dri2_surf->buffers[j] = *local; 1206bf215546Sopenharmony_ci break; 1207bf215546Sopenharmony_ci } 1208bf215546Sopenharmony_ci } 1209bf215546Sopenharmony_ci 1210bf215546Sopenharmony_ci *out_count = j; 1211bf215546Sopenharmony_ci if (j == 0) 1212bf215546Sopenharmony_ci return NULL; 1213bf215546Sopenharmony_ci 1214bf215546Sopenharmony_ci *width = dri2_surf->base.Width; 1215bf215546Sopenharmony_ci *height = dri2_surf->base.Height; 1216bf215546Sopenharmony_ci 1217bf215546Sopenharmony_ci return dri2_surf->buffers; 1218bf215546Sopenharmony_ci} 1219bf215546Sopenharmony_ci 1220bf215546Sopenharmony_cistatic __DRIbuffer * 1221bf215546Sopenharmony_cidri2_wl_get_buffers(__DRIdrawable * driDrawable, 1222bf215546Sopenharmony_ci int *width, int *height, 1223bf215546Sopenharmony_ci unsigned int *attachments, int count, 1224bf215546Sopenharmony_ci int *out_count, void *loaderPrivate) 1225bf215546Sopenharmony_ci{ 1226bf215546Sopenharmony_ci struct dri2_egl_surface *dri2_surf = loaderPrivate; 1227bf215546Sopenharmony_ci unsigned int *attachments_with_format; 1228bf215546Sopenharmony_ci __DRIbuffer *buffer; 1229bf215546Sopenharmony_ci int visual_idx = dri2_wl_visual_idx_from_fourcc(dri2_surf->format); 1230bf215546Sopenharmony_ci 1231bf215546Sopenharmony_ci if (visual_idx == -1) 1232bf215546Sopenharmony_ci return NULL; 1233bf215546Sopenharmony_ci 1234bf215546Sopenharmony_ci attachments_with_format = calloc(count, 2 * sizeof(unsigned int)); 1235bf215546Sopenharmony_ci if (!attachments_with_format) { 1236bf215546Sopenharmony_ci *out_count = 0; 1237bf215546Sopenharmony_ci return NULL; 1238bf215546Sopenharmony_ci } 1239bf215546Sopenharmony_ci 1240bf215546Sopenharmony_ci for (int i = 0; i < count; ++i) { 1241bf215546Sopenharmony_ci attachments_with_format[2*i] = attachments[i]; 1242bf215546Sopenharmony_ci attachments_with_format[2*i + 1] = dri2_wl_visuals[visual_idx].bpp; 1243bf215546Sopenharmony_ci } 1244bf215546Sopenharmony_ci 1245bf215546Sopenharmony_ci buffer = 1246bf215546Sopenharmony_ci dri2_wl_get_buffers_with_format(driDrawable, 1247bf215546Sopenharmony_ci width, height, 1248bf215546Sopenharmony_ci attachments_with_format, count, 1249bf215546Sopenharmony_ci out_count, loaderPrivate); 1250bf215546Sopenharmony_ci 1251bf215546Sopenharmony_ci free(attachments_with_format); 1252bf215546Sopenharmony_ci 1253bf215546Sopenharmony_ci return buffer; 1254bf215546Sopenharmony_ci} 1255bf215546Sopenharmony_ci 1256bf215546Sopenharmony_cistatic int 1257bf215546Sopenharmony_ciimage_get_buffers(__DRIdrawable *driDrawable, 1258bf215546Sopenharmony_ci unsigned int format, 1259bf215546Sopenharmony_ci uint32_t *stamp, 1260bf215546Sopenharmony_ci void *loaderPrivate, 1261bf215546Sopenharmony_ci uint32_t buffer_mask, 1262bf215546Sopenharmony_ci struct __DRIimageList *buffers) 1263bf215546Sopenharmony_ci{ 1264bf215546Sopenharmony_ci struct dri2_egl_surface *dri2_surf = loaderPrivate; 1265bf215546Sopenharmony_ci 1266bf215546Sopenharmony_ci if (update_buffers_if_needed(dri2_surf) < 0) 1267bf215546Sopenharmony_ci return 0; 1268bf215546Sopenharmony_ci 1269bf215546Sopenharmony_ci buffers->image_mask = __DRI_IMAGE_BUFFER_BACK; 1270bf215546Sopenharmony_ci buffers->back = dri2_surf->back->dri_image; 1271bf215546Sopenharmony_ci 1272bf215546Sopenharmony_ci return 1; 1273bf215546Sopenharmony_ci} 1274bf215546Sopenharmony_ci 1275bf215546Sopenharmony_cistatic void 1276bf215546Sopenharmony_cidri2_wl_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate) 1277bf215546Sopenharmony_ci{ 1278bf215546Sopenharmony_ci (void) driDrawable; 1279bf215546Sopenharmony_ci (void) loaderPrivate; 1280bf215546Sopenharmony_ci} 1281bf215546Sopenharmony_ci 1282bf215546Sopenharmony_cistatic unsigned 1283bf215546Sopenharmony_cidri2_wl_get_capability(void *loaderPrivate, enum dri_loader_cap cap) 1284bf215546Sopenharmony_ci{ 1285bf215546Sopenharmony_ci switch (cap) { 1286bf215546Sopenharmony_ci case DRI_LOADER_CAP_FP16: 1287bf215546Sopenharmony_ci return 1; 1288bf215546Sopenharmony_ci case DRI_LOADER_CAP_RGBA_ORDERING: 1289bf215546Sopenharmony_ci return 1; 1290bf215546Sopenharmony_ci default: 1291bf215546Sopenharmony_ci return 0; 1292bf215546Sopenharmony_ci } 1293bf215546Sopenharmony_ci} 1294bf215546Sopenharmony_ci 1295bf215546Sopenharmony_cistatic const __DRIdri2LoaderExtension dri2_loader_extension = { 1296bf215546Sopenharmony_ci .base = { __DRI_DRI2_LOADER, 4 }, 1297bf215546Sopenharmony_ci 1298bf215546Sopenharmony_ci .getBuffers = dri2_wl_get_buffers, 1299bf215546Sopenharmony_ci .flushFrontBuffer = dri2_wl_flush_front_buffer, 1300bf215546Sopenharmony_ci .getBuffersWithFormat = dri2_wl_get_buffers_with_format, 1301bf215546Sopenharmony_ci .getCapability = dri2_wl_get_capability, 1302bf215546Sopenharmony_ci}; 1303bf215546Sopenharmony_ci 1304bf215546Sopenharmony_cistatic const __DRIimageLoaderExtension image_loader_extension = { 1305bf215546Sopenharmony_ci .base = { __DRI_IMAGE_LOADER, 2 }, 1306bf215546Sopenharmony_ci 1307bf215546Sopenharmony_ci .getBuffers = image_get_buffers, 1308bf215546Sopenharmony_ci .flushFrontBuffer = dri2_wl_flush_front_buffer, 1309bf215546Sopenharmony_ci .getCapability = dri2_wl_get_capability, 1310bf215546Sopenharmony_ci}; 1311bf215546Sopenharmony_ci 1312bf215546Sopenharmony_cistatic void 1313bf215546Sopenharmony_ciwayland_throttle_callback(void *data, 1314bf215546Sopenharmony_ci struct wl_callback *callback, 1315bf215546Sopenharmony_ci uint32_t time) 1316bf215546Sopenharmony_ci{ 1317bf215546Sopenharmony_ci struct dri2_egl_surface *dri2_surf = data; 1318bf215546Sopenharmony_ci 1319bf215546Sopenharmony_ci dri2_surf->throttle_callback = NULL; 1320bf215546Sopenharmony_ci wl_callback_destroy(callback); 1321bf215546Sopenharmony_ci} 1322bf215546Sopenharmony_ci 1323bf215546Sopenharmony_cistatic const struct wl_callback_listener throttle_listener = { 1324bf215546Sopenharmony_ci .done = wayland_throttle_callback 1325bf215546Sopenharmony_ci}; 1326bf215546Sopenharmony_ci 1327bf215546Sopenharmony_cistatic EGLBoolean 1328bf215546Sopenharmony_ciget_fourcc(struct dri2_egl_display *dri2_dpy, 1329bf215546Sopenharmony_ci __DRIimage *image, int *fourcc) 1330bf215546Sopenharmony_ci{ 1331bf215546Sopenharmony_ci EGLBoolean query; 1332bf215546Sopenharmony_ci int dri_format; 1333bf215546Sopenharmony_ci int visual_idx; 1334bf215546Sopenharmony_ci 1335bf215546Sopenharmony_ci query = dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_FOURCC, 1336bf215546Sopenharmony_ci fourcc); 1337bf215546Sopenharmony_ci if (query) 1338bf215546Sopenharmony_ci return true; 1339bf215546Sopenharmony_ci 1340bf215546Sopenharmony_ci query = dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_FORMAT, 1341bf215546Sopenharmony_ci &dri_format); 1342bf215546Sopenharmony_ci if (!query) 1343bf215546Sopenharmony_ci return false; 1344bf215546Sopenharmony_ci 1345bf215546Sopenharmony_ci visual_idx = dri2_wl_visual_idx_from_dri_image_format(dri_format); 1346bf215546Sopenharmony_ci if (visual_idx == -1) 1347bf215546Sopenharmony_ci return false; 1348bf215546Sopenharmony_ci 1349bf215546Sopenharmony_ci *fourcc = dri2_wl_visuals[visual_idx].wl_drm_format; 1350bf215546Sopenharmony_ci return true; 1351bf215546Sopenharmony_ci} 1352bf215546Sopenharmony_ci 1353bf215546Sopenharmony_cistatic struct wl_buffer * 1354bf215546Sopenharmony_cicreate_wl_buffer(struct dri2_egl_display *dri2_dpy, 1355bf215546Sopenharmony_ci struct dri2_egl_surface *dri2_surf, 1356bf215546Sopenharmony_ci __DRIimage *image) 1357bf215546Sopenharmony_ci{ 1358bf215546Sopenharmony_ci struct wl_buffer *ret = NULL; 1359bf215546Sopenharmony_ci EGLBoolean query; 1360bf215546Sopenharmony_ci int width, height, fourcc, num_planes; 1361bf215546Sopenharmony_ci uint64_t modifier = DRM_FORMAT_MOD_INVALID; 1362bf215546Sopenharmony_ci 1363bf215546Sopenharmony_ci query = dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_WIDTH, &width); 1364bf215546Sopenharmony_ci query &= dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_HEIGHT, 1365bf215546Sopenharmony_ci &height); 1366bf215546Sopenharmony_ci query &= get_fourcc(dri2_dpy, image, &fourcc); 1367bf215546Sopenharmony_ci if (!query) 1368bf215546Sopenharmony_ci return NULL; 1369bf215546Sopenharmony_ci 1370bf215546Sopenharmony_ci query = dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_NUM_PLANES, 1371bf215546Sopenharmony_ci &num_planes); 1372bf215546Sopenharmony_ci if (!query) 1373bf215546Sopenharmony_ci num_planes = 1; 1374bf215546Sopenharmony_ci 1375bf215546Sopenharmony_ci if (dri2_dpy->image->base.version >= 15) { 1376bf215546Sopenharmony_ci int mod_hi, mod_lo; 1377bf215546Sopenharmony_ci 1378bf215546Sopenharmony_ci query = dri2_dpy->image->queryImage(image, 1379bf215546Sopenharmony_ci __DRI_IMAGE_ATTRIB_MODIFIER_UPPER, 1380bf215546Sopenharmony_ci &mod_hi); 1381bf215546Sopenharmony_ci query &= dri2_dpy->image->queryImage(image, 1382bf215546Sopenharmony_ci __DRI_IMAGE_ATTRIB_MODIFIER_LOWER, 1383bf215546Sopenharmony_ci &mod_lo); 1384bf215546Sopenharmony_ci if (query) { 1385bf215546Sopenharmony_ci modifier = combine_u32_into_u64(mod_hi, mod_lo); 1386bf215546Sopenharmony_ci } 1387bf215546Sopenharmony_ci } 1388bf215546Sopenharmony_ci 1389bf215546Sopenharmony_ci bool supported_modifier = false; 1390bf215546Sopenharmony_ci bool mod_invalid_supported = false; 1391bf215546Sopenharmony_ci int visual_idx = dri2_wl_visual_idx_from_fourcc(fourcc); 1392bf215546Sopenharmony_ci assert(visual_idx != -1); 1393bf215546Sopenharmony_ci 1394bf215546Sopenharmony_ci uint64_t *mod; 1395bf215546Sopenharmony_ci u_vector_foreach(mod, &dri2_dpy->formats.modifiers[visual_idx]) { 1396bf215546Sopenharmony_ci if (*mod == DRM_FORMAT_MOD_INVALID) { 1397bf215546Sopenharmony_ci mod_invalid_supported = true; 1398bf215546Sopenharmony_ci } 1399bf215546Sopenharmony_ci if (*mod == modifier) { 1400bf215546Sopenharmony_ci supported_modifier = true; 1401bf215546Sopenharmony_ci break; 1402bf215546Sopenharmony_ci } 1403bf215546Sopenharmony_ci } 1404bf215546Sopenharmony_ci if (!supported_modifier && mod_invalid_supported) { 1405bf215546Sopenharmony_ci /* If the server has advertised DRM_FORMAT_MOD_INVALID then we trust 1406bf215546Sopenharmony_ci * that the client has allocated the buffer with the right implicit 1407bf215546Sopenharmony_ci * modifier for the format, even though it's allocated a buffer the 1408bf215546Sopenharmony_ci * server hasn't explicitly claimed to support. */ 1409bf215546Sopenharmony_ci modifier = DRM_FORMAT_MOD_INVALID; 1410bf215546Sopenharmony_ci supported_modifier = true; 1411bf215546Sopenharmony_ci } 1412bf215546Sopenharmony_ci 1413bf215546Sopenharmony_ci if (dri2_dpy->wl_dmabuf && supported_modifier) { 1414bf215546Sopenharmony_ci struct zwp_linux_buffer_params_v1 *params; 1415bf215546Sopenharmony_ci int i; 1416bf215546Sopenharmony_ci 1417bf215546Sopenharmony_ci /* We don't need a wrapper for wl_dmabuf objects, because we have to 1418bf215546Sopenharmony_ci * create the intermediate params object; we can set the queue on this, 1419bf215546Sopenharmony_ci * and the wl_buffer inherits it race-free. */ 1420bf215546Sopenharmony_ci params = zwp_linux_dmabuf_v1_create_params(dri2_dpy->wl_dmabuf); 1421bf215546Sopenharmony_ci if (dri2_surf) 1422bf215546Sopenharmony_ci wl_proxy_set_queue((struct wl_proxy *) params, dri2_surf->wl_queue); 1423bf215546Sopenharmony_ci 1424bf215546Sopenharmony_ci for (i = 0; i < num_planes; i++) { 1425bf215546Sopenharmony_ci __DRIimage *p_image; 1426bf215546Sopenharmony_ci int stride, offset; 1427bf215546Sopenharmony_ci int fd = -1; 1428bf215546Sopenharmony_ci 1429bf215546Sopenharmony_ci p_image = dri2_dpy->image->fromPlanar(image, i, NULL); 1430bf215546Sopenharmony_ci if (!p_image) { 1431bf215546Sopenharmony_ci assert(i == 0); 1432bf215546Sopenharmony_ci p_image = image; 1433bf215546Sopenharmony_ci } 1434bf215546Sopenharmony_ci 1435bf215546Sopenharmony_ci query = dri2_dpy->image->queryImage(p_image, 1436bf215546Sopenharmony_ci __DRI_IMAGE_ATTRIB_FD, 1437bf215546Sopenharmony_ci &fd); 1438bf215546Sopenharmony_ci query &= dri2_dpy->image->queryImage(p_image, 1439bf215546Sopenharmony_ci __DRI_IMAGE_ATTRIB_STRIDE, 1440bf215546Sopenharmony_ci &stride); 1441bf215546Sopenharmony_ci query &= dri2_dpy->image->queryImage(p_image, 1442bf215546Sopenharmony_ci __DRI_IMAGE_ATTRIB_OFFSET, 1443bf215546Sopenharmony_ci &offset); 1444bf215546Sopenharmony_ci if (image != p_image) 1445bf215546Sopenharmony_ci dri2_dpy->image->destroyImage(p_image); 1446bf215546Sopenharmony_ci 1447bf215546Sopenharmony_ci if (!query) { 1448bf215546Sopenharmony_ci if (fd >= 0) 1449bf215546Sopenharmony_ci close(fd); 1450bf215546Sopenharmony_ci zwp_linux_buffer_params_v1_destroy(params); 1451bf215546Sopenharmony_ci return NULL; 1452bf215546Sopenharmony_ci } 1453bf215546Sopenharmony_ci 1454bf215546Sopenharmony_ci zwp_linux_buffer_params_v1_add(params, fd, i, offset, stride, 1455bf215546Sopenharmony_ci modifier >> 32, modifier & 0xffffffff); 1456bf215546Sopenharmony_ci close(fd); 1457bf215546Sopenharmony_ci } 1458bf215546Sopenharmony_ci 1459bf215546Sopenharmony_ci ret = zwp_linux_buffer_params_v1_create_immed(params, width, height, 1460bf215546Sopenharmony_ci fourcc, 0); 1461bf215546Sopenharmony_ci zwp_linux_buffer_params_v1_destroy(params); 1462bf215546Sopenharmony_ci } else { 1463bf215546Sopenharmony_ci struct wl_drm *wl_drm = 1464bf215546Sopenharmony_ci dri2_surf ? dri2_surf->wl_drm_wrapper : dri2_dpy->wl_drm; 1465bf215546Sopenharmony_ci int fd = -1, stride; 1466bf215546Sopenharmony_ci 1467bf215546Sopenharmony_ci if (num_planes > 1) 1468bf215546Sopenharmony_ci return NULL; 1469bf215546Sopenharmony_ci 1470bf215546Sopenharmony_ci query = dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_FD, &fd); 1471bf215546Sopenharmony_ci query &= dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_STRIDE, &stride); 1472bf215546Sopenharmony_ci if (!query) { 1473bf215546Sopenharmony_ci if (fd >= 0) 1474bf215546Sopenharmony_ci close(fd); 1475bf215546Sopenharmony_ci return NULL; 1476bf215546Sopenharmony_ci } 1477bf215546Sopenharmony_ci 1478bf215546Sopenharmony_ci ret = wl_drm_create_prime_buffer(wl_drm, fd, width, height, fourcc, 0, 1479bf215546Sopenharmony_ci stride, 0, 0, 0, 0); 1480bf215546Sopenharmony_ci close(fd); 1481bf215546Sopenharmony_ci } 1482bf215546Sopenharmony_ci 1483bf215546Sopenharmony_ci return ret; 1484bf215546Sopenharmony_ci} 1485bf215546Sopenharmony_ci 1486bf215546Sopenharmony_cistatic EGLBoolean 1487bf215546Sopenharmony_citry_damage_buffer(struct dri2_egl_surface *dri2_surf, 1488bf215546Sopenharmony_ci const EGLint *rects, 1489bf215546Sopenharmony_ci EGLint n_rects) 1490bf215546Sopenharmony_ci{ 1491bf215546Sopenharmony_ci if (wl_proxy_get_version((struct wl_proxy *) dri2_surf->wl_surface_wrapper) 1492bf215546Sopenharmony_ci < WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION) 1493bf215546Sopenharmony_ci return EGL_FALSE; 1494bf215546Sopenharmony_ci 1495bf215546Sopenharmony_ci for (int i = 0; i < n_rects; i++) { 1496bf215546Sopenharmony_ci const int *rect = &rects[i * 4]; 1497bf215546Sopenharmony_ci 1498bf215546Sopenharmony_ci wl_surface_damage_buffer(dri2_surf->wl_surface_wrapper, 1499bf215546Sopenharmony_ci rect[0], 1500bf215546Sopenharmony_ci dri2_surf->base.Height - rect[1] - rect[3], 1501bf215546Sopenharmony_ci rect[2], rect[3]); 1502bf215546Sopenharmony_ci } 1503bf215546Sopenharmony_ci return EGL_TRUE; 1504bf215546Sopenharmony_ci} 1505bf215546Sopenharmony_ci 1506bf215546Sopenharmony_ci/** 1507bf215546Sopenharmony_ci * Called via eglSwapBuffers(), drv->SwapBuffers(). 1508bf215546Sopenharmony_ci */ 1509bf215546Sopenharmony_cistatic EGLBoolean 1510bf215546Sopenharmony_cidri2_wl_swap_buffers_with_damage(_EGLDisplay *disp, 1511bf215546Sopenharmony_ci _EGLSurface *draw, 1512bf215546Sopenharmony_ci const EGLint *rects, 1513bf215546Sopenharmony_ci EGLint n_rects) 1514bf215546Sopenharmony_ci{ 1515bf215546Sopenharmony_ci struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1516bf215546Sopenharmony_ci struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw); 1517bf215546Sopenharmony_ci 1518bf215546Sopenharmony_ci if (!dri2_surf->wl_win) 1519bf215546Sopenharmony_ci return _eglError(EGL_BAD_NATIVE_WINDOW, "dri2_swap_buffers"); 1520bf215546Sopenharmony_ci 1521bf215546Sopenharmony_ci while (dri2_surf->throttle_callback != NULL) 1522bf215546Sopenharmony_ci if (wl_display_dispatch_queue(dri2_dpy->wl_dpy, 1523bf215546Sopenharmony_ci dri2_surf->wl_queue) == -1) 1524bf215546Sopenharmony_ci return -1; 1525bf215546Sopenharmony_ci 1526bf215546Sopenharmony_ci for (int i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) 1527bf215546Sopenharmony_ci if (dri2_surf->color_buffers[i].age > 0) 1528bf215546Sopenharmony_ci dri2_surf->color_buffers[i].age++; 1529bf215546Sopenharmony_ci 1530bf215546Sopenharmony_ci /* Make sure we have a back buffer in case we're swapping without ever 1531bf215546Sopenharmony_ci * rendering. */ 1532bf215546Sopenharmony_ci if (update_buffers_if_needed(dri2_surf) < 0) 1533bf215546Sopenharmony_ci return _eglError(EGL_BAD_ALLOC, "dri2_swap_buffers"); 1534bf215546Sopenharmony_ci 1535bf215546Sopenharmony_ci if (draw->SwapInterval > 0) { 1536bf215546Sopenharmony_ci dri2_surf->throttle_callback = 1537bf215546Sopenharmony_ci wl_surface_frame(dri2_surf->wl_surface_wrapper); 1538bf215546Sopenharmony_ci wl_callback_add_listener(dri2_surf->throttle_callback, 1539bf215546Sopenharmony_ci &throttle_listener, dri2_surf); 1540bf215546Sopenharmony_ci } 1541bf215546Sopenharmony_ci 1542bf215546Sopenharmony_ci dri2_surf->back->age = 1; 1543bf215546Sopenharmony_ci dri2_surf->current = dri2_surf->back; 1544bf215546Sopenharmony_ci dri2_surf->back = NULL; 1545bf215546Sopenharmony_ci 1546bf215546Sopenharmony_ci if (!dri2_surf->current->wl_buffer) { 1547bf215546Sopenharmony_ci __DRIimage *image; 1548bf215546Sopenharmony_ci 1549bf215546Sopenharmony_ci if (dri2_dpy->is_different_gpu) 1550bf215546Sopenharmony_ci image = dri2_surf->current->linear_copy; 1551bf215546Sopenharmony_ci else 1552bf215546Sopenharmony_ci image = dri2_surf->current->dri_image; 1553bf215546Sopenharmony_ci 1554bf215546Sopenharmony_ci dri2_surf->current->wl_buffer = 1555bf215546Sopenharmony_ci create_wl_buffer(dri2_dpy, dri2_surf, image); 1556bf215546Sopenharmony_ci 1557bf215546Sopenharmony_ci dri2_surf->current->wl_release = false; 1558bf215546Sopenharmony_ci 1559bf215546Sopenharmony_ci wl_buffer_add_listener(dri2_surf->current->wl_buffer, 1560bf215546Sopenharmony_ci &wl_buffer_listener, dri2_surf); 1561bf215546Sopenharmony_ci } 1562bf215546Sopenharmony_ci 1563bf215546Sopenharmony_ci wl_surface_attach(dri2_surf->wl_surface_wrapper, 1564bf215546Sopenharmony_ci dri2_surf->current->wl_buffer, 1565bf215546Sopenharmony_ci dri2_surf->dx, dri2_surf->dy); 1566bf215546Sopenharmony_ci 1567bf215546Sopenharmony_ci dri2_surf->wl_win->attached_width = dri2_surf->base.Width; 1568bf215546Sopenharmony_ci dri2_surf->wl_win->attached_height = dri2_surf->base.Height; 1569bf215546Sopenharmony_ci /* reset resize growing parameters */ 1570bf215546Sopenharmony_ci dri2_surf->dx = 0; 1571bf215546Sopenharmony_ci dri2_surf->dy = 0; 1572bf215546Sopenharmony_ci 1573bf215546Sopenharmony_ci /* If the compositor doesn't support damage_buffer, we deliberately 1574bf215546Sopenharmony_ci * ignore the damage region and post maximum damage, due to 1575bf215546Sopenharmony_ci * https://bugs.freedesktop.org/78190 */ 1576bf215546Sopenharmony_ci if (!n_rects || !try_damage_buffer(dri2_surf, rects, n_rects)) 1577bf215546Sopenharmony_ci wl_surface_damage(dri2_surf->wl_surface_wrapper, 1578bf215546Sopenharmony_ci 0, 0, INT32_MAX, INT32_MAX); 1579bf215546Sopenharmony_ci 1580bf215546Sopenharmony_ci if (dri2_dpy->is_different_gpu) { 1581bf215546Sopenharmony_ci _EGLContext *ctx = _eglGetCurrentContext(); 1582bf215546Sopenharmony_ci struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); 1583bf215546Sopenharmony_ci dri2_dpy->image->blitImage(dri2_ctx->dri_context, 1584bf215546Sopenharmony_ci dri2_surf->current->linear_copy, 1585bf215546Sopenharmony_ci dri2_surf->current->dri_image, 1586bf215546Sopenharmony_ci 0, 0, dri2_surf->base.Width, 1587bf215546Sopenharmony_ci dri2_surf->base.Height, 1588bf215546Sopenharmony_ci 0, 0, dri2_surf->base.Width, 1589bf215546Sopenharmony_ci dri2_surf->base.Height, 0); 1590bf215546Sopenharmony_ci } 1591bf215546Sopenharmony_ci 1592bf215546Sopenharmony_ci dri2_flush_drawable_for_swapbuffers(disp, draw); 1593bf215546Sopenharmony_ci dri2_dpy->flush->invalidate(dri2_surf->dri_drawable); 1594bf215546Sopenharmony_ci 1595bf215546Sopenharmony_ci wl_surface_commit(dri2_surf->wl_surface_wrapper); 1596bf215546Sopenharmony_ci 1597bf215546Sopenharmony_ci /* If we're not waiting for a frame callback then we'll at least throttle 1598bf215546Sopenharmony_ci * to a sync callback so that we always give a chance for the compositor to 1599bf215546Sopenharmony_ci * handle the commit and send a release event before checking for a free 1600bf215546Sopenharmony_ci * buffer */ 1601bf215546Sopenharmony_ci if (dri2_surf->throttle_callback == NULL) { 1602bf215546Sopenharmony_ci dri2_surf->throttle_callback = wl_display_sync(dri2_surf->wl_dpy_wrapper); 1603bf215546Sopenharmony_ci wl_callback_add_listener(dri2_surf->throttle_callback, 1604bf215546Sopenharmony_ci &throttle_listener, dri2_surf); 1605bf215546Sopenharmony_ci } 1606bf215546Sopenharmony_ci 1607bf215546Sopenharmony_ci wl_display_flush(dri2_dpy->wl_dpy); 1608bf215546Sopenharmony_ci 1609bf215546Sopenharmony_ci return EGL_TRUE; 1610bf215546Sopenharmony_ci} 1611bf215546Sopenharmony_ci 1612bf215546Sopenharmony_cistatic EGLint 1613bf215546Sopenharmony_cidri2_wl_query_buffer_age(_EGLDisplay *disp, _EGLSurface *surface) 1614bf215546Sopenharmony_ci{ 1615bf215546Sopenharmony_ci struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surface); 1616bf215546Sopenharmony_ci 1617bf215546Sopenharmony_ci if (update_buffers_if_needed(dri2_surf) < 0) { 1618bf215546Sopenharmony_ci _eglError(EGL_BAD_ALLOC, "dri2_query_buffer_age"); 1619bf215546Sopenharmony_ci return -1; 1620bf215546Sopenharmony_ci } 1621bf215546Sopenharmony_ci 1622bf215546Sopenharmony_ci return dri2_surf->back->age; 1623bf215546Sopenharmony_ci} 1624bf215546Sopenharmony_ci 1625bf215546Sopenharmony_cistatic EGLBoolean 1626bf215546Sopenharmony_cidri2_wl_swap_buffers(_EGLDisplay *disp, _EGLSurface *draw) 1627bf215546Sopenharmony_ci{ 1628bf215546Sopenharmony_ci return dri2_wl_swap_buffers_with_damage(disp, draw, NULL, 0); 1629bf215546Sopenharmony_ci} 1630bf215546Sopenharmony_ci 1631bf215546Sopenharmony_cistatic struct wl_buffer * 1632bf215546Sopenharmony_cidri2_wl_create_wayland_buffer_from_image(_EGLDisplay *disp, _EGLImage *img) 1633bf215546Sopenharmony_ci{ 1634bf215546Sopenharmony_ci struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1635bf215546Sopenharmony_ci struct dri2_egl_image *dri2_img = dri2_egl_image(img); 1636bf215546Sopenharmony_ci __DRIimage *image = dri2_img->dri_image; 1637bf215546Sopenharmony_ci struct wl_buffer *buffer; 1638bf215546Sopenharmony_ci int format, visual_idx; 1639bf215546Sopenharmony_ci 1640bf215546Sopenharmony_ci /* Check the upstream display supports this buffer's format. */ 1641bf215546Sopenharmony_ci dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_FORMAT, &format); 1642bf215546Sopenharmony_ci visual_idx = dri2_wl_visual_idx_from_dri_image_format(format); 1643bf215546Sopenharmony_ci if (visual_idx == -1) 1644bf215546Sopenharmony_ci goto bad_format; 1645bf215546Sopenharmony_ci 1646bf215546Sopenharmony_ci if (!BITSET_TEST(dri2_dpy->formats.formats_bitmap, visual_idx)) 1647bf215546Sopenharmony_ci goto bad_format; 1648bf215546Sopenharmony_ci 1649bf215546Sopenharmony_ci buffer = create_wl_buffer(dri2_dpy, NULL, image); 1650bf215546Sopenharmony_ci 1651bf215546Sopenharmony_ci /* The buffer object will have been created with our internal event queue 1652bf215546Sopenharmony_ci * because it is using wl_dmabuf/wl_drm as a proxy factory. We want the 1653bf215546Sopenharmony_ci * buffer to be used by the application so we'll reset it to the display's 1654bf215546Sopenharmony_ci * default event queue. This isn't actually racy, as the only event the 1655bf215546Sopenharmony_ci * buffer can get is a buffer release, which doesn't happen with an explicit 1656bf215546Sopenharmony_ci * attach. */ 1657bf215546Sopenharmony_ci if (buffer) 1658bf215546Sopenharmony_ci wl_proxy_set_queue((struct wl_proxy *) buffer, NULL); 1659bf215546Sopenharmony_ci 1660bf215546Sopenharmony_ci return buffer; 1661bf215546Sopenharmony_ci 1662bf215546Sopenharmony_cibad_format: 1663bf215546Sopenharmony_ci _eglError(EGL_BAD_MATCH, "unsupported image format"); 1664bf215546Sopenharmony_ci return NULL; 1665bf215546Sopenharmony_ci} 1666bf215546Sopenharmony_ci 1667bf215546Sopenharmony_cistatic int 1668bf215546Sopenharmony_cidri2_wl_authenticate(_EGLDisplay *disp, uint32_t id) 1669bf215546Sopenharmony_ci{ 1670bf215546Sopenharmony_ci struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1671bf215546Sopenharmony_ci int ret = 0; 1672bf215546Sopenharmony_ci 1673bf215546Sopenharmony_ci if (dri2_dpy->is_render_node) { 1674bf215546Sopenharmony_ci _eglLog(_EGL_WARNING, "wayland-egl: client asks server to " 1675bf215546Sopenharmony_ci "authenticate for render-nodes"); 1676bf215546Sopenharmony_ci return 0; 1677bf215546Sopenharmony_ci } 1678bf215546Sopenharmony_ci dri2_dpy->authenticated = false; 1679bf215546Sopenharmony_ci 1680bf215546Sopenharmony_ci wl_drm_authenticate(dri2_dpy->wl_drm, id); 1681bf215546Sopenharmony_ci if (roundtrip(dri2_dpy) < 0) 1682bf215546Sopenharmony_ci ret = -1; 1683bf215546Sopenharmony_ci 1684bf215546Sopenharmony_ci if (!dri2_dpy->authenticated) 1685bf215546Sopenharmony_ci ret = -1; 1686bf215546Sopenharmony_ci 1687bf215546Sopenharmony_ci /* reset authenticated */ 1688bf215546Sopenharmony_ci dri2_dpy->authenticated = true; 1689bf215546Sopenharmony_ci 1690bf215546Sopenharmony_ci return ret; 1691bf215546Sopenharmony_ci} 1692bf215546Sopenharmony_ci 1693bf215546Sopenharmony_cistatic void 1694bf215546Sopenharmony_cidrm_handle_device(void *data, struct wl_drm *drm, const char *device) 1695bf215546Sopenharmony_ci{ 1696bf215546Sopenharmony_ci struct dri2_egl_display *dri2_dpy = data; 1697bf215546Sopenharmony_ci drm_magic_t magic; 1698bf215546Sopenharmony_ci 1699bf215546Sopenharmony_ci dri2_dpy->device_name = strdup(device); 1700bf215546Sopenharmony_ci if (!dri2_dpy->device_name) 1701bf215546Sopenharmony_ci return; 1702bf215546Sopenharmony_ci 1703bf215546Sopenharmony_ci dri2_dpy->fd = loader_open_device(dri2_dpy->device_name); 1704bf215546Sopenharmony_ci if (dri2_dpy->fd == -1) { 1705bf215546Sopenharmony_ci _eglLog(_EGL_WARNING, "wayland-egl: could not open %s (%s)", 1706bf215546Sopenharmony_ci dri2_dpy->device_name, strerror(errno)); 1707bf215546Sopenharmony_ci free(dri2_dpy->device_name); 1708bf215546Sopenharmony_ci dri2_dpy->device_name = NULL; 1709bf215546Sopenharmony_ci return; 1710bf215546Sopenharmony_ci } 1711bf215546Sopenharmony_ci 1712bf215546Sopenharmony_ci if (drmGetNodeTypeFromFd(dri2_dpy->fd) == DRM_NODE_RENDER) { 1713bf215546Sopenharmony_ci dri2_dpy->authenticated = true; 1714bf215546Sopenharmony_ci } else { 1715bf215546Sopenharmony_ci if (drmGetMagic(dri2_dpy->fd, &magic)) { 1716bf215546Sopenharmony_ci close(dri2_dpy->fd); 1717bf215546Sopenharmony_ci dri2_dpy->fd = -1; 1718bf215546Sopenharmony_ci free(dri2_dpy->device_name); 1719bf215546Sopenharmony_ci dri2_dpy->device_name = NULL; 1720bf215546Sopenharmony_ci _eglLog(_EGL_WARNING, "wayland-egl: drmGetMagic failed"); 1721bf215546Sopenharmony_ci return; 1722bf215546Sopenharmony_ci } 1723bf215546Sopenharmony_ci wl_drm_authenticate(dri2_dpy->wl_drm, magic); 1724bf215546Sopenharmony_ci } 1725bf215546Sopenharmony_ci} 1726bf215546Sopenharmony_ci 1727bf215546Sopenharmony_cistatic void 1728bf215546Sopenharmony_cidrm_handle_format(void *data, struct wl_drm *drm, uint32_t format) 1729bf215546Sopenharmony_ci{ 1730bf215546Sopenharmony_ci struct dri2_egl_display *dri2_dpy = data; 1731bf215546Sopenharmony_ci int visual_idx = dri2_wl_visual_idx_from_fourcc(format); 1732bf215546Sopenharmony_ci 1733bf215546Sopenharmony_ci if (visual_idx == -1) 1734bf215546Sopenharmony_ci return; 1735bf215546Sopenharmony_ci 1736bf215546Sopenharmony_ci BITSET_SET(dri2_dpy->formats.formats_bitmap, visual_idx); 1737bf215546Sopenharmony_ci} 1738bf215546Sopenharmony_ci 1739bf215546Sopenharmony_cistatic void 1740bf215546Sopenharmony_cidrm_handle_capabilities(void *data, struct wl_drm *drm, uint32_t value) 1741bf215546Sopenharmony_ci{ 1742bf215546Sopenharmony_ci struct dri2_egl_display *dri2_dpy = data; 1743bf215546Sopenharmony_ci 1744bf215546Sopenharmony_ci dri2_dpy->capabilities = value; 1745bf215546Sopenharmony_ci} 1746bf215546Sopenharmony_ci 1747bf215546Sopenharmony_cistatic void 1748bf215546Sopenharmony_cidrm_handle_authenticated(void *data, struct wl_drm *drm) 1749bf215546Sopenharmony_ci{ 1750bf215546Sopenharmony_ci struct dri2_egl_display *dri2_dpy = data; 1751bf215546Sopenharmony_ci 1752bf215546Sopenharmony_ci dri2_dpy->authenticated = true; 1753bf215546Sopenharmony_ci} 1754bf215546Sopenharmony_ci 1755bf215546Sopenharmony_cistatic const struct wl_drm_listener drm_listener = { 1756bf215546Sopenharmony_ci .device = drm_handle_device, 1757bf215546Sopenharmony_ci .format = drm_handle_format, 1758bf215546Sopenharmony_ci .authenticated = drm_handle_authenticated, 1759bf215546Sopenharmony_ci .capabilities = drm_handle_capabilities 1760bf215546Sopenharmony_ci}; 1761bf215546Sopenharmony_ci 1762bf215546Sopenharmony_cistatic void 1763bf215546Sopenharmony_cidmabuf_ignore_format(void *data, struct zwp_linux_dmabuf_v1 *dmabuf, 1764bf215546Sopenharmony_ci uint32_t format) 1765bf215546Sopenharmony_ci{ 1766bf215546Sopenharmony_ci /* formats are implicitly advertised by the 'modifier' event, so ignore */ 1767bf215546Sopenharmony_ci} 1768bf215546Sopenharmony_ci 1769bf215546Sopenharmony_cistatic void 1770bf215546Sopenharmony_cidmabuf_handle_modifier(void *data, struct zwp_linux_dmabuf_v1 *dmabuf, 1771bf215546Sopenharmony_ci uint32_t format, uint32_t modifier_hi, 1772bf215546Sopenharmony_ci uint32_t modifier_lo) 1773bf215546Sopenharmony_ci{ 1774bf215546Sopenharmony_ci struct dri2_egl_display *dri2_dpy = data; 1775bf215546Sopenharmony_ci int visual_idx = dri2_wl_visual_idx_from_fourcc(format); 1776bf215546Sopenharmony_ci uint64_t *mod; 1777bf215546Sopenharmony_ci 1778bf215546Sopenharmony_ci /* Ignore this if the compositor advertised dma-buf feedback. From version 4 1779bf215546Sopenharmony_ci * onwards (when dma-buf feedback was introduced), the compositor should not 1780bf215546Sopenharmony_ci * advertise this event anymore, but let's keep this for safety. */ 1781bf215546Sopenharmony_ci if (dri2_dpy->wl_dmabuf_feedback) 1782bf215546Sopenharmony_ci return; 1783bf215546Sopenharmony_ci 1784bf215546Sopenharmony_ci if (visual_idx == -1) 1785bf215546Sopenharmony_ci return; 1786bf215546Sopenharmony_ci 1787bf215546Sopenharmony_ci BITSET_SET(dri2_dpy->formats.formats_bitmap, visual_idx); 1788bf215546Sopenharmony_ci 1789bf215546Sopenharmony_ci mod = u_vector_add(&dri2_dpy->formats.modifiers[visual_idx]); 1790bf215546Sopenharmony_ci if (mod) 1791bf215546Sopenharmony_ci *mod = combine_u32_into_u64(modifier_hi, modifier_lo); 1792bf215546Sopenharmony_ci} 1793bf215546Sopenharmony_ci 1794bf215546Sopenharmony_cistatic const struct zwp_linux_dmabuf_v1_listener dmabuf_listener = { 1795bf215546Sopenharmony_ci .format = dmabuf_ignore_format, 1796bf215546Sopenharmony_ci .modifier = dmabuf_handle_modifier, 1797bf215546Sopenharmony_ci}; 1798bf215546Sopenharmony_ci 1799bf215546Sopenharmony_cistatic void 1800bf215546Sopenharmony_ciwl_drm_bind(struct dri2_egl_display *dri2_dpy) 1801bf215546Sopenharmony_ci{ 1802bf215546Sopenharmony_ci dri2_dpy->wl_drm = wl_registry_bind(dri2_dpy->wl_registry, dri2_dpy->wl_drm_name, 1803bf215546Sopenharmony_ci &wl_drm_interface, dri2_dpy->wl_drm_version); 1804bf215546Sopenharmony_ci wl_drm_add_listener(dri2_dpy->wl_drm, &drm_listener, dri2_dpy); 1805bf215546Sopenharmony_ci} 1806bf215546Sopenharmony_ci 1807bf215546Sopenharmony_cistatic void 1808bf215546Sopenharmony_cidefault_dmabuf_feedback_format_table(void *data, 1809bf215546Sopenharmony_ci struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1, 1810bf215546Sopenharmony_ci int32_t fd, uint32_t size) 1811bf215546Sopenharmony_ci{ 1812bf215546Sopenharmony_ci struct dri2_egl_display *dri2_dpy = data; 1813bf215546Sopenharmony_ci 1814bf215546Sopenharmony_ci dri2_dpy->format_table.size = size; 1815bf215546Sopenharmony_ci dri2_dpy->format_table.data = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); 1816bf215546Sopenharmony_ci 1817bf215546Sopenharmony_ci close(fd); 1818bf215546Sopenharmony_ci} 1819bf215546Sopenharmony_ci 1820bf215546Sopenharmony_cistatic void 1821bf215546Sopenharmony_cidefault_dmabuf_feedback_main_device(void *data, 1822bf215546Sopenharmony_ci struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback, 1823bf215546Sopenharmony_ci struct wl_array *device) 1824bf215546Sopenharmony_ci{ 1825bf215546Sopenharmony_ci struct dri2_egl_display *dri2_dpy = data; 1826bf215546Sopenharmony_ci char *node; 1827bf215546Sopenharmony_ci int fd; 1828bf215546Sopenharmony_ci dev_t dev; 1829bf215546Sopenharmony_ci 1830bf215546Sopenharmony_ci /* Given the device, look for a render node and try to open it. */ 1831bf215546Sopenharmony_ci memcpy(&dev, device->data, sizeof(dev)); 1832bf215546Sopenharmony_ci node = loader_get_render_node(dev); 1833bf215546Sopenharmony_ci if (!node) 1834bf215546Sopenharmony_ci return; 1835bf215546Sopenharmony_ci fd = loader_open_device(node); 1836bf215546Sopenharmony_ci if (fd == -1) { 1837bf215546Sopenharmony_ci free(node); 1838bf215546Sopenharmony_ci return; 1839bf215546Sopenharmony_ci } 1840bf215546Sopenharmony_ci 1841bf215546Sopenharmony_ci dri2_dpy->device_name = node; 1842bf215546Sopenharmony_ci dri2_dpy->fd = fd; 1843bf215546Sopenharmony_ci dri2_dpy->authenticated = true; 1844bf215546Sopenharmony_ci} 1845bf215546Sopenharmony_ci 1846bf215546Sopenharmony_cistatic void 1847bf215546Sopenharmony_cidefault_dmabuf_feedback_tranche_target_device(void *data, 1848bf215546Sopenharmony_ci struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback, 1849bf215546Sopenharmony_ci struct wl_array *device) 1850bf215546Sopenharmony_ci{ 1851bf215546Sopenharmony_ci /* ignore this event */ 1852bf215546Sopenharmony_ci} 1853bf215546Sopenharmony_ci 1854bf215546Sopenharmony_cistatic void 1855bf215546Sopenharmony_cidefault_dmabuf_feedback_tranche_flags(void *data, 1856bf215546Sopenharmony_ci struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback, 1857bf215546Sopenharmony_ci uint32_t flags) 1858bf215546Sopenharmony_ci{ 1859bf215546Sopenharmony_ci /* ignore this event */ 1860bf215546Sopenharmony_ci} 1861bf215546Sopenharmony_ci 1862bf215546Sopenharmony_cistatic void 1863bf215546Sopenharmony_cidefault_dmabuf_feedback_tranche_formats(void *data, 1864bf215546Sopenharmony_ci struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback, 1865bf215546Sopenharmony_ci struct wl_array *indices) 1866bf215546Sopenharmony_ci{ 1867bf215546Sopenharmony_ci struct dri2_egl_display *dri2_dpy = data; 1868bf215546Sopenharmony_ci uint64_t *modifier_ptr, modifier; 1869bf215546Sopenharmony_ci uint32_t format; 1870bf215546Sopenharmony_ci uint16_t *index; 1871bf215546Sopenharmony_ci int visual_idx; 1872bf215546Sopenharmony_ci 1873bf215546Sopenharmony_ci if (dri2_dpy->format_table.data == MAP_FAILED) { 1874bf215546Sopenharmony_ci _eglLog(_EGL_WARNING, "wayland-egl: we could not map the format table " 1875bf215546Sopenharmony_ci "so we won't be able to use this batch of dma-buf " 1876bf215546Sopenharmony_ci "feedback events."); 1877bf215546Sopenharmony_ci return; 1878bf215546Sopenharmony_ci } 1879bf215546Sopenharmony_ci if (dri2_dpy->format_table.data == NULL) { 1880bf215546Sopenharmony_ci _eglLog(_EGL_WARNING, "wayland-egl: compositor didn't advertise a format " 1881bf215546Sopenharmony_ci "table, so we won't be able to use this batch of dma-buf " 1882bf215546Sopenharmony_ci "feedback events."); 1883bf215546Sopenharmony_ci return; 1884bf215546Sopenharmony_ci } 1885bf215546Sopenharmony_ci 1886bf215546Sopenharmony_ci wl_array_for_each(index, indices) { 1887bf215546Sopenharmony_ci format = dri2_dpy->format_table.data[*index].format; 1888bf215546Sopenharmony_ci modifier = dri2_dpy->format_table.data[*index].modifier; 1889bf215546Sopenharmony_ci 1890bf215546Sopenharmony_ci /* skip formats that we don't support */ 1891bf215546Sopenharmony_ci visual_idx = dri2_wl_visual_idx_from_fourcc(format); 1892bf215546Sopenharmony_ci if (visual_idx == -1) 1893bf215546Sopenharmony_ci continue; 1894bf215546Sopenharmony_ci 1895bf215546Sopenharmony_ci BITSET_SET(dri2_dpy->formats.formats_bitmap, visual_idx); 1896bf215546Sopenharmony_ci modifier_ptr = u_vector_add(&dri2_dpy->formats.modifiers[visual_idx]); 1897bf215546Sopenharmony_ci if (modifier_ptr) 1898bf215546Sopenharmony_ci *modifier_ptr = modifier; 1899bf215546Sopenharmony_ci } 1900bf215546Sopenharmony_ci} 1901bf215546Sopenharmony_ci 1902bf215546Sopenharmony_cistatic void 1903bf215546Sopenharmony_cidefault_dmabuf_feedback_tranche_done(void *data, 1904bf215546Sopenharmony_ci struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback) 1905bf215546Sopenharmony_ci{ 1906bf215546Sopenharmony_ci /* ignore this event */ 1907bf215546Sopenharmony_ci} 1908bf215546Sopenharmony_ci 1909bf215546Sopenharmony_cistatic void 1910bf215546Sopenharmony_cidefault_dmabuf_feedback_done(void *data, 1911bf215546Sopenharmony_ci struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback) 1912bf215546Sopenharmony_ci{ 1913bf215546Sopenharmony_ci /* ignore this event */ 1914bf215546Sopenharmony_ci} 1915bf215546Sopenharmony_ci 1916bf215546Sopenharmony_cistatic const struct zwp_linux_dmabuf_feedback_v1_listener 1917bf215546Sopenharmony_cidmabuf_feedback_listener = { 1918bf215546Sopenharmony_ci .format_table = default_dmabuf_feedback_format_table, 1919bf215546Sopenharmony_ci .main_device = default_dmabuf_feedback_main_device, 1920bf215546Sopenharmony_ci .tranche_target_device = default_dmabuf_feedback_tranche_target_device, 1921bf215546Sopenharmony_ci .tranche_flags = default_dmabuf_feedback_tranche_flags, 1922bf215546Sopenharmony_ci .tranche_formats = default_dmabuf_feedback_tranche_formats, 1923bf215546Sopenharmony_ci .tranche_done = default_dmabuf_feedback_tranche_done, 1924bf215546Sopenharmony_ci .done = default_dmabuf_feedback_done, 1925bf215546Sopenharmony_ci}; 1926bf215546Sopenharmony_ci 1927bf215546Sopenharmony_cistatic void 1928bf215546Sopenharmony_ciregistry_handle_global_drm(void *data, struct wl_registry *registry, 1929bf215546Sopenharmony_ci uint32_t name, const char *interface, 1930bf215546Sopenharmony_ci uint32_t version) 1931bf215546Sopenharmony_ci{ 1932bf215546Sopenharmony_ci struct dri2_egl_display *dri2_dpy = data; 1933bf215546Sopenharmony_ci 1934bf215546Sopenharmony_ci if (strcmp(interface, "wl_drm") == 0) { 1935bf215546Sopenharmony_ci dri2_dpy->wl_drm_version = MIN2(version, 2); 1936bf215546Sopenharmony_ci dri2_dpy->wl_drm_name = name; 1937bf215546Sopenharmony_ci } else if (strcmp(interface, "zwp_linux_dmabuf_v1") == 0 && version >= 3) { 1938bf215546Sopenharmony_ci dri2_dpy->wl_dmabuf = 1939bf215546Sopenharmony_ci wl_registry_bind(registry, name, &zwp_linux_dmabuf_v1_interface, 1940bf215546Sopenharmony_ci MIN2(version, ZWP_LINUX_DMABUF_V1_GET_DEFAULT_FEEDBACK_SINCE_VERSION)); 1941bf215546Sopenharmony_ci zwp_linux_dmabuf_v1_add_listener(dri2_dpy->wl_dmabuf, &dmabuf_listener, 1942bf215546Sopenharmony_ci dri2_dpy); 1943bf215546Sopenharmony_ci } 1944bf215546Sopenharmony_ci} 1945bf215546Sopenharmony_ci 1946bf215546Sopenharmony_cistatic void 1947bf215546Sopenharmony_ciregistry_handle_global_remove(void *data, struct wl_registry *registry, 1948bf215546Sopenharmony_ci uint32_t name) 1949bf215546Sopenharmony_ci{ 1950bf215546Sopenharmony_ci} 1951bf215546Sopenharmony_ci 1952bf215546Sopenharmony_cistatic const struct wl_registry_listener registry_listener_drm = { 1953bf215546Sopenharmony_ci .global = registry_handle_global_drm, 1954bf215546Sopenharmony_ci .global_remove = registry_handle_global_remove 1955bf215546Sopenharmony_ci}; 1956bf215546Sopenharmony_ci 1957bf215546Sopenharmony_cistatic void 1958bf215546Sopenharmony_cidri2_wl_setup_swap_interval(_EGLDisplay *disp) 1959bf215546Sopenharmony_ci{ 1960bf215546Sopenharmony_ci /* We can't use values greater than 1 on Wayland because we are using the 1961bf215546Sopenharmony_ci * frame callback to synchronise the frame and the only way we be sure to 1962bf215546Sopenharmony_ci * get a frame callback is to attach a new buffer. Therefore we can't just 1963bf215546Sopenharmony_ci * sit drawing nothing to wait until the next ‘n’ frame callbacks */ 1964bf215546Sopenharmony_ci 1965bf215546Sopenharmony_ci dri2_setup_swap_interval(disp, 1); 1966bf215546Sopenharmony_ci} 1967bf215546Sopenharmony_ci 1968bf215546Sopenharmony_cistatic const struct dri2_egl_display_vtbl dri2_wl_display_vtbl = { 1969bf215546Sopenharmony_ci .authenticate = dri2_wl_authenticate, 1970bf215546Sopenharmony_ci .create_window_surface = dri2_wl_create_window_surface, 1971bf215546Sopenharmony_ci .create_pixmap_surface = dri2_wl_create_pixmap_surface, 1972bf215546Sopenharmony_ci .destroy_surface = dri2_wl_destroy_surface, 1973bf215546Sopenharmony_ci .swap_interval = dri2_wl_swap_interval, 1974bf215546Sopenharmony_ci .create_image = dri2_create_image_khr, 1975bf215546Sopenharmony_ci .swap_buffers = dri2_wl_swap_buffers, 1976bf215546Sopenharmony_ci .swap_buffers_with_damage = dri2_wl_swap_buffers_with_damage, 1977bf215546Sopenharmony_ci .query_buffer_age = dri2_wl_query_buffer_age, 1978bf215546Sopenharmony_ci .create_wayland_buffer_from_image = dri2_wl_create_wayland_buffer_from_image, 1979bf215546Sopenharmony_ci .get_dri_drawable = dri2_surface_get_dri_drawable, 1980bf215546Sopenharmony_ci}; 1981bf215546Sopenharmony_ci 1982bf215546Sopenharmony_cistatic const __DRIextension *dri2_loader_extensions[] = { 1983bf215546Sopenharmony_ci &dri2_loader_extension.base, 1984bf215546Sopenharmony_ci &image_loader_extension.base, 1985bf215546Sopenharmony_ci &image_lookup_extension.base, 1986bf215546Sopenharmony_ci &use_invalidate.base, 1987bf215546Sopenharmony_ci NULL, 1988bf215546Sopenharmony_ci}; 1989bf215546Sopenharmony_ci 1990bf215546Sopenharmony_cistatic const __DRIextension *image_loader_extensions[] = { 1991bf215546Sopenharmony_ci &image_loader_extension.base, 1992bf215546Sopenharmony_ci &image_lookup_extension.base, 1993bf215546Sopenharmony_ci &use_invalidate.base, 1994bf215546Sopenharmony_ci NULL, 1995bf215546Sopenharmony_ci}; 1996bf215546Sopenharmony_ci 1997bf215546Sopenharmony_cistatic EGLBoolean 1998bf215546Sopenharmony_cidri2_wl_add_configs_for_visuals(_EGLDisplay *disp) 1999bf215546Sopenharmony_ci{ 2000bf215546Sopenharmony_ci struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2001bf215546Sopenharmony_ci unsigned int format_count[ARRAY_SIZE(dri2_wl_visuals)] = { 0 }; 2002bf215546Sopenharmony_ci unsigned int count = 0; 2003bf215546Sopenharmony_ci bool assigned; 2004bf215546Sopenharmony_ci 2005bf215546Sopenharmony_ci for (unsigned i = 0; dri2_dpy->driver_configs[i]; i++) { 2006bf215546Sopenharmony_ci assigned = false; 2007bf215546Sopenharmony_ci 2008bf215546Sopenharmony_ci for (unsigned j = 0; j < ARRAY_SIZE(dri2_wl_visuals); j++) { 2009bf215546Sopenharmony_ci struct dri2_egl_config *dri2_conf; 2010bf215546Sopenharmony_ci 2011bf215546Sopenharmony_ci if (!BITSET_TEST(dri2_dpy->formats.formats_bitmap, j)) 2012bf215546Sopenharmony_ci continue; 2013bf215546Sopenharmony_ci 2014bf215546Sopenharmony_ci dri2_conf = dri2_add_config(disp, dri2_dpy->driver_configs[i], 2015bf215546Sopenharmony_ci count + 1, EGL_WINDOW_BIT, NULL, dri2_wl_visuals[j].rgba_shifts, dri2_wl_visuals[j].rgba_sizes); 2016bf215546Sopenharmony_ci if (dri2_conf) { 2017bf215546Sopenharmony_ci if (dri2_conf->base.ConfigID == count + 1) 2018bf215546Sopenharmony_ci count++; 2019bf215546Sopenharmony_ci format_count[j]++; 2020bf215546Sopenharmony_ci assigned = true; 2021bf215546Sopenharmony_ci } 2022bf215546Sopenharmony_ci } 2023bf215546Sopenharmony_ci 2024bf215546Sopenharmony_ci if (!assigned && dri2_dpy->is_different_gpu) { 2025bf215546Sopenharmony_ci struct dri2_egl_config *dri2_conf; 2026bf215546Sopenharmony_ci int alt_dri_image_format, c, s; 2027bf215546Sopenharmony_ci 2028bf215546Sopenharmony_ci /* No match for config. Try if we can blitImage convert to a visual */ 2029bf215546Sopenharmony_ci c = dri2_wl_visual_idx_from_config(dri2_dpy, 2030bf215546Sopenharmony_ci dri2_dpy->driver_configs[i], 2031bf215546Sopenharmony_ci false); 2032bf215546Sopenharmony_ci 2033bf215546Sopenharmony_ci if (c == -1) 2034bf215546Sopenharmony_ci continue; 2035bf215546Sopenharmony_ci 2036bf215546Sopenharmony_ci /* Find optimal target visual for blitImage conversion, if any. */ 2037bf215546Sopenharmony_ci alt_dri_image_format = dri2_wl_visuals[c].alt_dri_image_format; 2038bf215546Sopenharmony_ci s = dri2_wl_visual_idx_from_dri_image_format(alt_dri_image_format); 2039bf215546Sopenharmony_ci 2040bf215546Sopenharmony_ci if (s == -1 || !BITSET_TEST(dri2_dpy->formats.formats_bitmap, s)) 2041bf215546Sopenharmony_ci continue; 2042bf215546Sopenharmony_ci 2043bf215546Sopenharmony_ci /* Visual s works for the Wayland server, and c can be converted into s 2044bf215546Sopenharmony_ci * by our client gpu during PRIME blitImage conversion to a linear 2045bf215546Sopenharmony_ci * wl_buffer, so add visual c as supported by the client renderer. 2046bf215546Sopenharmony_ci */ 2047bf215546Sopenharmony_ci dri2_conf = dri2_add_config(disp, dri2_dpy->driver_configs[i], 2048bf215546Sopenharmony_ci count + 1, EGL_WINDOW_BIT, NULL, 2049bf215546Sopenharmony_ci dri2_wl_visuals[c].rgba_shifts, 2050bf215546Sopenharmony_ci dri2_wl_visuals[c].rgba_sizes); 2051bf215546Sopenharmony_ci if (dri2_conf) { 2052bf215546Sopenharmony_ci if (dri2_conf->base.ConfigID == count + 1) 2053bf215546Sopenharmony_ci count++; 2054bf215546Sopenharmony_ci format_count[c]++; 2055bf215546Sopenharmony_ci if (format_count[c] == 1) 2056bf215546Sopenharmony_ci _eglLog(_EGL_DEBUG, "Client format %s to server format %s via " 2057bf215546Sopenharmony_ci "PRIME blitImage.", dri2_wl_visuals[c].format_name, 2058bf215546Sopenharmony_ci dri2_wl_visuals[s].format_name); 2059bf215546Sopenharmony_ci } 2060bf215546Sopenharmony_ci } 2061bf215546Sopenharmony_ci } 2062bf215546Sopenharmony_ci 2063bf215546Sopenharmony_ci for (unsigned i = 0; i < ARRAY_SIZE(format_count); i++) { 2064bf215546Sopenharmony_ci if (!format_count[i]) { 2065bf215546Sopenharmony_ci _eglLog(_EGL_DEBUG, "No DRI config supports native format %s", 2066bf215546Sopenharmony_ci dri2_wl_visuals[i].format_name); 2067bf215546Sopenharmony_ci } 2068bf215546Sopenharmony_ci } 2069bf215546Sopenharmony_ci 2070bf215546Sopenharmony_ci return (count != 0); 2071bf215546Sopenharmony_ci} 2072bf215546Sopenharmony_ci 2073bf215546Sopenharmony_cistatic EGLBoolean 2074bf215546Sopenharmony_cidri2_initialize_wayland_drm(_EGLDisplay *disp) 2075bf215546Sopenharmony_ci{ 2076bf215546Sopenharmony_ci _EGLDevice *dev; 2077bf215546Sopenharmony_ci struct dri2_egl_display *dri2_dpy; 2078bf215546Sopenharmony_ci 2079bf215546Sopenharmony_ci dri2_dpy = calloc(1, sizeof *dri2_dpy); 2080bf215546Sopenharmony_ci if (!dri2_dpy) 2081bf215546Sopenharmony_ci return _eglError(EGL_BAD_ALLOC, "eglInitialize"); 2082bf215546Sopenharmony_ci 2083bf215546Sopenharmony_ci dri2_dpy->fd = -1; 2084bf215546Sopenharmony_ci disp->DriverData = (void *) dri2_dpy; 2085bf215546Sopenharmony_ci 2086bf215546Sopenharmony_ci if (dri2_wl_formats_init(&dri2_dpy->formats) < 0) 2087bf215546Sopenharmony_ci goto cleanup; 2088bf215546Sopenharmony_ci 2089bf215546Sopenharmony_ci if (disp->PlatformDisplay == NULL) { 2090bf215546Sopenharmony_ci dri2_dpy->wl_dpy = wl_display_connect(NULL); 2091bf215546Sopenharmony_ci if (dri2_dpy->wl_dpy == NULL) 2092bf215546Sopenharmony_ci goto cleanup; 2093bf215546Sopenharmony_ci dri2_dpy->own_device = true; 2094bf215546Sopenharmony_ci } else { 2095bf215546Sopenharmony_ci dri2_dpy->wl_dpy = disp->PlatformDisplay; 2096bf215546Sopenharmony_ci } 2097bf215546Sopenharmony_ci 2098bf215546Sopenharmony_ci dri2_dpy->wl_queue = wl_display_create_queue(dri2_dpy->wl_dpy); 2099bf215546Sopenharmony_ci 2100bf215546Sopenharmony_ci dri2_dpy->wl_dpy_wrapper = wl_proxy_create_wrapper(dri2_dpy->wl_dpy); 2101bf215546Sopenharmony_ci if (dri2_dpy->wl_dpy_wrapper == NULL) 2102bf215546Sopenharmony_ci goto cleanup; 2103bf215546Sopenharmony_ci 2104bf215546Sopenharmony_ci wl_proxy_set_queue((struct wl_proxy *) dri2_dpy->wl_dpy_wrapper, 2105bf215546Sopenharmony_ci dri2_dpy->wl_queue); 2106bf215546Sopenharmony_ci 2107bf215546Sopenharmony_ci if (dri2_dpy->own_device) 2108bf215546Sopenharmony_ci wl_display_dispatch_pending(dri2_dpy->wl_dpy); 2109bf215546Sopenharmony_ci 2110bf215546Sopenharmony_ci dri2_dpy->wl_registry = wl_display_get_registry(dri2_dpy->wl_dpy_wrapper); 2111bf215546Sopenharmony_ci wl_registry_add_listener(dri2_dpy->wl_registry, 2112bf215546Sopenharmony_ci ®istry_listener_drm, dri2_dpy); 2113bf215546Sopenharmony_ci 2114bf215546Sopenharmony_ci if (roundtrip(dri2_dpy) < 0) 2115bf215546Sopenharmony_ci goto cleanup; 2116bf215546Sopenharmony_ci 2117bf215546Sopenharmony_ci /* Get default dma-buf feedback */ 2118bf215546Sopenharmony_ci if (dri2_dpy->wl_dmabuf && zwp_linux_dmabuf_v1_get_version(dri2_dpy->wl_dmabuf) >= 2119bf215546Sopenharmony_ci ZWP_LINUX_DMABUF_V1_GET_DEFAULT_FEEDBACK_SINCE_VERSION) { 2120bf215546Sopenharmony_ci dmabuf_feedback_format_table_init(&dri2_dpy->format_table); 2121bf215546Sopenharmony_ci dri2_dpy->wl_dmabuf_feedback = 2122bf215546Sopenharmony_ci zwp_linux_dmabuf_v1_get_default_feedback(dri2_dpy->wl_dmabuf); 2123bf215546Sopenharmony_ci zwp_linux_dmabuf_feedback_v1_add_listener(dri2_dpy->wl_dmabuf_feedback, 2124bf215546Sopenharmony_ci &dmabuf_feedback_listener, dri2_dpy); 2125bf215546Sopenharmony_ci } 2126bf215546Sopenharmony_ci 2127bf215546Sopenharmony_ci if (roundtrip(dri2_dpy) < 0) 2128bf215546Sopenharmony_ci goto cleanup; 2129bf215546Sopenharmony_ci 2130bf215546Sopenharmony_ci /* Destroy the default dma-buf feedback and the format table. */ 2131bf215546Sopenharmony_ci if (dri2_dpy->wl_dmabuf_feedback) { 2132bf215546Sopenharmony_ci zwp_linux_dmabuf_feedback_v1_destroy(dri2_dpy->wl_dmabuf_feedback); 2133bf215546Sopenharmony_ci dri2_dpy->wl_dmabuf_feedback = NULL; 2134bf215546Sopenharmony_ci dmabuf_feedback_format_table_fini(&dri2_dpy->format_table); 2135bf215546Sopenharmony_ci } 2136bf215546Sopenharmony_ci 2137bf215546Sopenharmony_ci /* We couldn't retrieve a render node from the dma-buf feedback (or the 2138bf215546Sopenharmony_ci * feedback was not advertised at all), so we must fallback to wl_drm. */ 2139bf215546Sopenharmony_ci if (dri2_dpy->fd == -1) { 2140bf215546Sopenharmony_ci /* wl_drm not advertised by compositor, so can't continue */ 2141bf215546Sopenharmony_ci if (dri2_dpy->wl_drm_name == 0) 2142bf215546Sopenharmony_ci goto cleanup; 2143bf215546Sopenharmony_ci wl_drm_bind(dri2_dpy); 2144bf215546Sopenharmony_ci 2145bf215546Sopenharmony_ci if (dri2_dpy->wl_drm == NULL) 2146bf215546Sopenharmony_ci goto cleanup; 2147bf215546Sopenharmony_ci if (roundtrip(dri2_dpy) < 0 || dri2_dpy->fd == -1) 2148bf215546Sopenharmony_ci goto cleanup; 2149bf215546Sopenharmony_ci 2150bf215546Sopenharmony_ci if (!dri2_dpy->authenticated && 2151bf215546Sopenharmony_ci (roundtrip(dri2_dpy) < 0 || !dri2_dpy->authenticated)) 2152bf215546Sopenharmony_ci goto cleanup; 2153bf215546Sopenharmony_ci } 2154bf215546Sopenharmony_ci 2155bf215546Sopenharmony_ci dri2_dpy->fd = loader_get_user_preferred_fd(dri2_dpy->fd, 2156bf215546Sopenharmony_ci &dri2_dpy->is_different_gpu); 2157bf215546Sopenharmony_ci dev = _eglAddDevice(dri2_dpy->fd, false); 2158bf215546Sopenharmony_ci if (!dev) { 2159bf215546Sopenharmony_ci _eglError(EGL_NOT_INITIALIZED, "DRI2: failed to find EGLDevice"); 2160bf215546Sopenharmony_ci goto cleanup; 2161bf215546Sopenharmony_ci } 2162bf215546Sopenharmony_ci 2163bf215546Sopenharmony_ci disp->Device = dev; 2164bf215546Sopenharmony_ci 2165bf215546Sopenharmony_ci if (dri2_dpy->is_different_gpu) { 2166bf215546Sopenharmony_ci free(dri2_dpy->device_name); 2167bf215546Sopenharmony_ci dri2_dpy->device_name = loader_get_device_name_for_fd(dri2_dpy->fd); 2168bf215546Sopenharmony_ci if (!dri2_dpy->device_name) { 2169bf215546Sopenharmony_ci _eglError(EGL_BAD_ALLOC, "wayland-egl: failed to get device name " 2170bf215546Sopenharmony_ci "for requested GPU"); 2171bf215546Sopenharmony_ci goto cleanup; 2172bf215546Sopenharmony_ci } 2173bf215546Sopenharmony_ci } 2174bf215546Sopenharmony_ci 2175bf215546Sopenharmony_ci /* we have to do the check now, because loader_get_user_preferred_fd 2176bf215546Sopenharmony_ci * will return a render-node when the requested gpu is different 2177bf215546Sopenharmony_ci * to the server, but also if the client asks for the same gpu than 2178bf215546Sopenharmony_ci * the server by requesting its pci-id */ 2179bf215546Sopenharmony_ci dri2_dpy->is_render_node = drmGetNodeTypeFromFd(dri2_dpy->fd) == DRM_NODE_RENDER; 2180bf215546Sopenharmony_ci 2181bf215546Sopenharmony_ci dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd); 2182bf215546Sopenharmony_ci if (dri2_dpy->driver_name == NULL) { 2183bf215546Sopenharmony_ci _eglError(EGL_BAD_ALLOC, "DRI2: failed to get driver name"); 2184bf215546Sopenharmony_ci goto cleanup; 2185bf215546Sopenharmony_ci } 2186bf215546Sopenharmony_ci 2187bf215546Sopenharmony_ci /* render nodes cannot use Gem names, and thus do not support 2188bf215546Sopenharmony_ci * the __DRI_DRI2_LOADER extension */ 2189bf215546Sopenharmony_ci if (!dri2_dpy->is_render_node) { 2190bf215546Sopenharmony_ci dri2_dpy->loader_extensions = dri2_loader_extensions; 2191bf215546Sopenharmony_ci if (!dri2_load_driver(disp)) { 2192bf215546Sopenharmony_ci _eglError(EGL_BAD_ALLOC, "DRI2: failed to load driver"); 2193bf215546Sopenharmony_ci goto cleanup; 2194bf215546Sopenharmony_ci } 2195bf215546Sopenharmony_ci } else { 2196bf215546Sopenharmony_ci dri2_dpy->loader_extensions = image_loader_extensions; 2197bf215546Sopenharmony_ci if (!dri2_load_driver_dri3(disp)) { 2198bf215546Sopenharmony_ci _eglError(EGL_BAD_ALLOC, "DRI3: failed to load driver"); 2199bf215546Sopenharmony_ci goto cleanup; 2200bf215546Sopenharmony_ci } 2201bf215546Sopenharmony_ci } 2202bf215546Sopenharmony_ci 2203bf215546Sopenharmony_ci if (!dri2_create_screen(disp)) 2204bf215546Sopenharmony_ci goto cleanup; 2205bf215546Sopenharmony_ci 2206bf215546Sopenharmony_ci if (!dri2_setup_extensions(disp)) 2207bf215546Sopenharmony_ci goto cleanup; 2208bf215546Sopenharmony_ci 2209bf215546Sopenharmony_ci dri2_setup_screen(disp); 2210bf215546Sopenharmony_ci 2211bf215546Sopenharmony_ci dri2_wl_setup_swap_interval(disp); 2212bf215546Sopenharmony_ci 2213bf215546Sopenharmony_ci if (dri2_dpy->wl_drm) { 2214bf215546Sopenharmony_ci /* To use Prime, we must have _DRI_IMAGE v7 at least. createImageFromFds 2215bf215546Sopenharmony_ci * support indicates that Prime export/import is supported by the driver. 2216bf215546Sopenharmony_ci * We deprecated the support to GEM names API, so we bail out if the 2217bf215546Sopenharmony_ci * driver does not suport Prime. */ 2218bf215546Sopenharmony_ci if (!(dri2_dpy->capabilities & WL_DRM_CAPABILITY_PRIME) || 2219bf215546Sopenharmony_ci (dri2_dpy->image->base.version < 7) || 2220bf215546Sopenharmony_ci (dri2_dpy->image->createImageFromFds == NULL)) { 2221bf215546Sopenharmony_ci _eglLog(_EGL_WARNING, "wayland-egl: display does not support prime"); 2222bf215546Sopenharmony_ci goto cleanup; 2223bf215546Sopenharmony_ci } 2224bf215546Sopenharmony_ci } 2225bf215546Sopenharmony_ci 2226bf215546Sopenharmony_ci if (dri2_dpy->is_different_gpu && 2227bf215546Sopenharmony_ci (dri2_dpy->image->base.version < 9 || 2228bf215546Sopenharmony_ci dri2_dpy->image->blitImage == NULL)) { 2229bf215546Sopenharmony_ci _eglLog(_EGL_WARNING, "wayland-egl: Different GPU selected, but the " 2230bf215546Sopenharmony_ci "Image extension in the driver is not " 2231bf215546Sopenharmony_ci "compatible. Version 9 or later and blitImage() " 2232bf215546Sopenharmony_ci "are required"); 2233bf215546Sopenharmony_ci goto cleanup; 2234bf215546Sopenharmony_ci } 2235bf215546Sopenharmony_ci 2236bf215546Sopenharmony_ci if (!dri2_wl_add_configs_for_visuals(disp)) { 2237bf215546Sopenharmony_ci _eglError(EGL_NOT_INITIALIZED, "DRI2: failed to add configs"); 2238bf215546Sopenharmony_ci goto cleanup; 2239bf215546Sopenharmony_ci } 2240bf215546Sopenharmony_ci 2241bf215546Sopenharmony_ci dri2_set_WL_bind_wayland_display(disp); 2242bf215546Sopenharmony_ci /* When cannot convert EGLImage to wl_buffer when on a different gpu, 2243bf215546Sopenharmony_ci * because the buffer of the EGLImage has likely a tiling mode the server 2244bf215546Sopenharmony_ci * gpu won't support. These is no way to check for now. Thus do not support the 2245bf215546Sopenharmony_ci * extension */ 2246bf215546Sopenharmony_ci if (!dri2_dpy->is_different_gpu) 2247bf215546Sopenharmony_ci disp->Extensions.WL_create_wayland_buffer_from_image = EGL_TRUE; 2248bf215546Sopenharmony_ci 2249bf215546Sopenharmony_ci disp->Extensions.EXT_buffer_age = EGL_TRUE; 2250bf215546Sopenharmony_ci 2251bf215546Sopenharmony_ci disp->Extensions.EXT_swap_buffers_with_damage = EGL_TRUE; 2252bf215546Sopenharmony_ci 2253bf215546Sopenharmony_ci disp->Extensions.EXT_present_opaque = EGL_TRUE; 2254bf215546Sopenharmony_ci 2255bf215546Sopenharmony_ci /* Fill vtbl last to prevent accidentally calling virtual function during 2256bf215546Sopenharmony_ci * initialization. 2257bf215546Sopenharmony_ci */ 2258bf215546Sopenharmony_ci dri2_dpy->vtbl = &dri2_wl_display_vtbl; 2259bf215546Sopenharmony_ci 2260bf215546Sopenharmony_ci return EGL_TRUE; 2261bf215546Sopenharmony_ci 2262bf215546Sopenharmony_ci cleanup: 2263bf215546Sopenharmony_ci dri2_display_destroy(disp); 2264bf215546Sopenharmony_ci return EGL_FALSE; 2265bf215546Sopenharmony_ci} 2266bf215546Sopenharmony_ci 2267bf215546Sopenharmony_cistatic int 2268bf215546Sopenharmony_cidri2_wl_swrast_get_stride_for_format(int format, int w) 2269bf215546Sopenharmony_ci{ 2270bf215546Sopenharmony_ci int visual_idx = dri2_wl_visual_idx_from_shm_format(format); 2271bf215546Sopenharmony_ci 2272bf215546Sopenharmony_ci assume(visual_idx != -1); 2273bf215546Sopenharmony_ci 2274bf215546Sopenharmony_ci return w * (dri2_wl_visuals[visual_idx].bpp / 8); 2275bf215546Sopenharmony_ci} 2276bf215546Sopenharmony_ci 2277bf215546Sopenharmony_cistatic EGLBoolean 2278bf215546Sopenharmony_cidri2_wl_swrast_allocate_buffer(struct dri2_egl_surface *dri2_surf, 2279bf215546Sopenharmony_ci int format, int w, int h, 2280bf215546Sopenharmony_ci void **data, int *size, 2281bf215546Sopenharmony_ci struct wl_buffer **buffer) 2282bf215546Sopenharmony_ci{ 2283bf215546Sopenharmony_ci struct dri2_egl_display *dri2_dpy = 2284bf215546Sopenharmony_ci dri2_egl_display(dri2_surf->base.Resource.Display); 2285bf215546Sopenharmony_ci struct wl_shm_pool *pool; 2286bf215546Sopenharmony_ci int fd, stride, size_map; 2287bf215546Sopenharmony_ci void *data_map; 2288bf215546Sopenharmony_ci 2289bf215546Sopenharmony_ci stride = dri2_wl_swrast_get_stride_for_format(format, w); 2290bf215546Sopenharmony_ci size_map = h * stride; 2291bf215546Sopenharmony_ci 2292bf215546Sopenharmony_ci /* Create a shareable buffer */ 2293bf215546Sopenharmony_ci fd = os_create_anonymous_file(size_map, NULL); 2294bf215546Sopenharmony_ci if (fd < 0) 2295bf215546Sopenharmony_ci return EGL_FALSE; 2296bf215546Sopenharmony_ci 2297bf215546Sopenharmony_ci data_map = mmap(NULL, size_map, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 2298bf215546Sopenharmony_ci if (data_map == MAP_FAILED) { 2299bf215546Sopenharmony_ci close(fd); 2300bf215546Sopenharmony_ci return EGL_FALSE; 2301bf215546Sopenharmony_ci } 2302bf215546Sopenharmony_ci 2303bf215546Sopenharmony_ci /* Share it in a wl_buffer */ 2304bf215546Sopenharmony_ci pool = wl_shm_create_pool(dri2_dpy->wl_shm, fd, size_map); 2305bf215546Sopenharmony_ci wl_proxy_set_queue((struct wl_proxy *)pool, dri2_surf->wl_queue); 2306bf215546Sopenharmony_ci *buffer = wl_shm_pool_create_buffer(pool, 0, w, h, stride, format); 2307bf215546Sopenharmony_ci wl_shm_pool_destroy(pool); 2308bf215546Sopenharmony_ci close(fd); 2309bf215546Sopenharmony_ci 2310bf215546Sopenharmony_ci *data = data_map; 2311bf215546Sopenharmony_ci *size = size_map; 2312bf215546Sopenharmony_ci return EGL_TRUE; 2313bf215546Sopenharmony_ci} 2314bf215546Sopenharmony_ci 2315bf215546Sopenharmony_cistatic int 2316bf215546Sopenharmony_ciswrast_update_buffers(struct dri2_egl_surface *dri2_surf) 2317bf215546Sopenharmony_ci{ 2318bf215546Sopenharmony_ci struct dri2_egl_display *dri2_dpy = 2319bf215546Sopenharmony_ci dri2_egl_display(dri2_surf->base.Resource.Display); 2320bf215546Sopenharmony_ci bool zink = dri2_surf->base.Resource.Display->Options.Zink; 2321bf215546Sopenharmony_ci 2322bf215546Sopenharmony_ci /* we need to do the following operations only once per frame */ 2323bf215546Sopenharmony_ci if (dri2_surf->back) 2324bf215546Sopenharmony_ci return 0; 2325bf215546Sopenharmony_ci 2326bf215546Sopenharmony_ci if (dri2_surf->wl_win && 2327bf215546Sopenharmony_ci (dri2_surf->base.Width != dri2_surf->wl_win->width || 2328bf215546Sopenharmony_ci dri2_surf->base.Height != dri2_surf->wl_win->height)) { 2329bf215546Sopenharmony_ci 2330bf215546Sopenharmony_ci if (!zink) 2331bf215546Sopenharmony_ci dri2_wl_release_buffers(dri2_surf); 2332bf215546Sopenharmony_ci 2333bf215546Sopenharmony_ci dri2_surf->base.Width = dri2_surf->wl_win->width; 2334bf215546Sopenharmony_ci dri2_surf->base.Height = dri2_surf->wl_win->height; 2335bf215546Sopenharmony_ci dri2_surf->dx = dri2_surf->wl_win->dx; 2336bf215546Sopenharmony_ci dri2_surf->dy = dri2_surf->wl_win->dy; 2337bf215546Sopenharmony_ci dri2_surf->current = NULL; 2338bf215546Sopenharmony_ci } 2339bf215546Sopenharmony_ci 2340bf215546Sopenharmony_ci /* find back buffer */ 2341bf215546Sopenharmony_ci 2342bf215546Sopenharmony_ci /* There might be a buffer release already queued that wasn't processed */ 2343bf215546Sopenharmony_ci wl_display_dispatch_queue_pending(dri2_dpy->wl_dpy, dri2_surf->wl_queue); 2344bf215546Sopenharmony_ci 2345bf215546Sopenharmony_ci /* try get free buffer already created */ 2346bf215546Sopenharmony_ci for (int i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) { 2347bf215546Sopenharmony_ci if (!dri2_surf->color_buffers[i].locked && 2348bf215546Sopenharmony_ci dri2_surf->color_buffers[i].wl_buffer) { 2349bf215546Sopenharmony_ci dri2_surf->back = &dri2_surf->color_buffers[i]; 2350bf215546Sopenharmony_ci break; 2351bf215546Sopenharmony_ci } 2352bf215546Sopenharmony_ci } 2353bf215546Sopenharmony_ci 2354bf215546Sopenharmony_ci /* else choose any another free location */ 2355bf215546Sopenharmony_ci if (!dri2_surf->back) { 2356bf215546Sopenharmony_ci for (int i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) { 2357bf215546Sopenharmony_ci if (!dri2_surf->color_buffers[i].locked) { 2358bf215546Sopenharmony_ci dri2_surf->back = &dri2_surf->color_buffers[i]; 2359bf215546Sopenharmony_ci if (zink) 2360bf215546Sopenharmony_ci continue; 2361bf215546Sopenharmony_ci if (!dri2_wl_swrast_allocate_buffer(dri2_surf, 2362bf215546Sopenharmony_ci dri2_surf->format, 2363bf215546Sopenharmony_ci dri2_surf->base.Width, 2364bf215546Sopenharmony_ci dri2_surf->base.Height, 2365bf215546Sopenharmony_ci &dri2_surf->back->data, 2366bf215546Sopenharmony_ci &dri2_surf->back->data_size, 2367bf215546Sopenharmony_ci &dri2_surf->back->wl_buffer)) { 2368bf215546Sopenharmony_ci _eglError(EGL_BAD_ALLOC, "failed to allocate color buffer"); 2369bf215546Sopenharmony_ci return -1; 2370bf215546Sopenharmony_ci } 2371bf215546Sopenharmony_ci wl_buffer_add_listener(dri2_surf->back->wl_buffer, 2372bf215546Sopenharmony_ci &wl_buffer_listener, dri2_surf); 2373bf215546Sopenharmony_ci break; 2374bf215546Sopenharmony_ci } 2375bf215546Sopenharmony_ci } 2376bf215546Sopenharmony_ci } 2377bf215546Sopenharmony_ci 2378bf215546Sopenharmony_ci if (!dri2_surf->back) { 2379bf215546Sopenharmony_ci _eglError(EGL_BAD_ALLOC, "failed to find free buffer"); 2380bf215546Sopenharmony_ci return -1; 2381bf215546Sopenharmony_ci } 2382bf215546Sopenharmony_ci 2383bf215546Sopenharmony_ci dri2_surf->back->locked = true; 2384bf215546Sopenharmony_ci 2385bf215546Sopenharmony_ci /* If we have an extra unlocked buffer at this point, we had to do triple 2386bf215546Sopenharmony_ci * buffering for a while, but now can go back to just double buffering. 2387bf215546Sopenharmony_ci * That means we can free any unlocked buffer now. To avoid toggling between 2388bf215546Sopenharmony_ci * going back to double buffering and needing to allocate another buffer too 2389bf215546Sopenharmony_ci * fast we let the unneeded buffer sit around for a short while. */ 2390bf215546Sopenharmony_ci for (int i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) { 2391bf215546Sopenharmony_ci if (!dri2_surf->color_buffers[i].locked && 2392bf215546Sopenharmony_ci dri2_surf->color_buffers[i].wl_buffer && 2393bf215546Sopenharmony_ci dri2_surf->color_buffers[i].age > BUFFER_TRIM_AGE_HYSTERESIS) { 2394bf215546Sopenharmony_ci if (!zink) { 2395bf215546Sopenharmony_ci wl_buffer_destroy(dri2_surf->color_buffers[i].wl_buffer); 2396bf215546Sopenharmony_ci munmap(dri2_surf->color_buffers[i].data, 2397bf215546Sopenharmony_ci dri2_surf->color_buffers[i].data_size); 2398bf215546Sopenharmony_ci } 2399bf215546Sopenharmony_ci dri2_surf->color_buffers[i].wl_buffer = NULL; 2400bf215546Sopenharmony_ci dri2_surf->color_buffers[i].data = NULL; 2401bf215546Sopenharmony_ci dri2_surf->color_buffers[i].age = 0; 2402bf215546Sopenharmony_ci } 2403bf215546Sopenharmony_ci } 2404bf215546Sopenharmony_ci 2405bf215546Sopenharmony_ci return 0; 2406bf215546Sopenharmony_ci} 2407bf215546Sopenharmony_ci 2408bf215546Sopenharmony_cistatic void* 2409bf215546Sopenharmony_cidri2_wl_swrast_get_frontbuffer_data(struct dri2_egl_surface *dri2_surf) 2410bf215546Sopenharmony_ci{ 2411bf215546Sopenharmony_ci /* if there has been a resize: */ 2412bf215546Sopenharmony_ci if (!dri2_surf->current) 2413bf215546Sopenharmony_ci return NULL; 2414bf215546Sopenharmony_ci 2415bf215546Sopenharmony_ci return dri2_surf->current->data; 2416bf215546Sopenharmony_ci} 2417bf215546Sopenharmony_ci 2418bf215546Sopenharmony_cistatic void* 2419bf215546Sopenharmony_cidri2_wl_swrast_get_backbuffer_data(struct dri2_egl_surface *dri2_surf) 2420bf215546Sopenharmony_ci{ 2421bf215546Sopenharmony_ci assert(dri2_surf->back); 2422bf215546Sopenharmony_ci return dri2_surf->back->data; 2423bf215546Sopenharmony_ci} 2424bf215546Sopenharmony_ci 2425bf215546Sopenharmony_cistatic void 2426bf215546Sopenharmony_cidri2_wl_swrast_commit_backbuffer(struct dri2_egl_surface *dri2_surf) 2427bf215546Sopenharmony_ci{ 2428bf215546Sopenharmony_ci struct dri2_egl_display *dri2_dpy = dri2_egl_display(dri2_surf->base.Resource.Display); 2429bf215546Sopenharmony_ci 2430bf215546Sopenharmony_ci while (dri2_surf->throttle_callback != NULL) 2431bf215546Sopenharmony_ci if (wl_display_dispatch_queue(dri2_dpy->wl_dpy, 2432bf215546Sopenharmony_ci dri2_surf->wl_queue) == -1) 2433bf215546Sopenharmony_ci return; 2434bf215546Sopenharmony_ci 2435bf215546Sopenharmony_ci if (dri2_surf->base.SwapInterval > 0) { 2436bf215546Sopenharmony_ci dri2_surf->throttle_callback = 2437bf215546Sopenharmony_ci wl_surface_frame(dri2_surf->wl_surface_wrapper); 2438bf215546Sopenharmony_ci wl_callback_add_listener(dri2_surf->throttle_callback, 2439bf215546Sopenharmony_ci &throttle_listener, dri2_surf); 2440bf215546Sopenharmony_ci } 2441bf215546Sopenharmony_ci 2442bf215546Sopenharmony_ci dri2_surf->current = dri2_surf->back; 2443bf215546Sopenharmony_ci dri2_surf->back = NULL; 2444bf215546Sopenharmony_ci 2445bf215546Sopenharmony_ci wl_surface_attach(dri2_surf->wl_surface_wrapper, 2446bf215546Sopenharmony_ci dri2_surf->current->wl_buffer, 2447bf215546Sopenharmony_ci dri2_surf->dx, dri2_surf->dy); 2448bf215546Sopenharmony_ci 2449bf215546Sopenharmony_ci dri2_surf->wl_win->attached_width = dri2_surf->base.Width; 2450bf215546Sopenharmony_ci dri2_surf->wl_win->attached_height = dri2_surf->base.Height; 2451bf215546Sopenharmony_ci /* reset resize growing parameters */ 2452bf215546Sopenharmony_ci dri2_surf->dx = 0; 2453bf215546Sopenharmony_ci dri2_surf->dy = 0; 2454bf215546Sopenharmony_ci 2455bf215546Sopenharmony_ci wl_surface_damage(dri2_surf->wl_surface_wrapper, 2456bf215546Sopenharmony_ci 0, 0, INT32_MAX, INT32_MAX); 2457bf215546Sopenharmony_ci wl_surface_commit(dri2_surf->wl_surface_wrapper); 2458bf215546Sopenharmony_ci 2459bf215546Sopenharmony_ci /* If we're not waiting for a frame callback then we'll at least throttle 2460bf215546Sopenharmony_ci * to a sync callback so that we always give a chance for the compositor to 2461bf215546Sopenharmony_ci * handle the commit and send a release event before checking for a free 2462bf215546Sopenharmony_ci * buffer */ 2463bf215546Sopenharmony_ci if (dri2_surf->throttle_callback == NULL) { 2464bf215546Sopenharmony_ci dri2_surf->throttle_callback = wl_display_sync(dri2_surf->wl_dpy_wrapper); 2465bf215546Sopenharmony_ci wl_callback_add_listener(dri2_surf->throttle_callback, 2466bf215546Sopenharmony_ci &throttle_listener, dri2_surf); 2467bf215546Sopenharmony_ci } 2468bf215546Sopenharmony_ci 2469bf215546Sopenharmony_ci wl_display_flush(dri2_dpy->wl_dpy); 2470bf215546Sopenharmony_ci} 2471bf215546Sopenharmony_ci 2472bf215546Sopenharmony_cistatic void 2473bf215546Sopenharmony_cidri2_wl_swrast_get_drawable_info(__DRIdrawable * draw, 2474bf215546Sopenharmony_ci int *x, int *y, int *w, int *h, 2475bf215546Sopenharmony_ci void *loaderPrivate) 2476bf215546Sopenharmony_ci{ 2477bf215546Sopenharmony_ci struct dri2_egl_surface *dri2_surf = loaderPrivate; 2478bf215546Sopenharmony_ci 2479bf215546Sopenharmony_ci (void) swrast_update_buffers(dri2_surf); 2480bf215546Sopenharmony_ci *x = 0; 2481bf215546Sopenharmony_ci *y = 0; 2482bf215546Sopenharmony_ci *w = dri2_surf->base.Width; 2483bf215546Sopenharmony_ci *h = dri2_surf->base.Height; 2484bf215546Sopenharmony_ci} 2485bf215546Sopenharmony_ci 2486bf215546Sopenharmony_cistatic void 2487bf215546Sopenharmony_cidri2_wl_swrast_get_image(__DRIdrawable * read, 2488bf215546Sopenharmony_ci int x, int y, int w, int h, 2489bf215546Sopenharmony_ci char *data, void *loaderPrivate) 2490bf215546Sopenharmony_ci{ 2491bf215546Sopenharmony_ci struct dri2_egl_surface *dri2_surf = loaderPrivate; 2492bf215546Sopenharmony_ci int copy_width = dri2_wl_swrast_get_stride_for_format(dri2_surf->format, w); 2493bf215546Sopenharmony_ci int x_offset = dri2_wl_swrast_get_stride_for_format(dri2_surf->format, x); 2494bf215546Sopenharmony_ci int src_stride = dri2_wl_swrast_get_stride_for_format(dri2_surf->format, dri2_surf->base.Width); 2495bf215546Sopenharmony_ci int dst_stride = copy_width; 2496bf215546Sopenharmony_ci char *src, *dst; 2497bf215546Sopenharmony_ci 2498bf215546Sopenharmony_ci src = dri2_wl_swrast_get_frontbuffer_data(dri2_surf); 2499bf215546Sopenharmony_ci if (!src) { 2500bf215546Sopenharmony_ci memset(data, 0, copy_width * h); 2501bf215546Sopenharmony_ci return; 2502bf215546Sopenharmony_ci } 2503bf215546Sopenharmony_ci 2504bf215546Sopenharmony_ci assert(data != src); 2505bf215546Sopenharmony_ci assert(copy_width <= src_stride); 2506bf215546Sopenharmony_ci 2507bf215546Sopenharmony_ci src += x_offset; 2508bf215546Sopenharmony_ci src += y * src_stride; 2509bf215546Sopenharmony_ci dst = data; 2510bf215546Sopenharmony_ci 2511bf215546Sopenharmony_ci if (copy_width > src_stride-x_offset) 2512bf215546Sopenharmony_ci copy_width = src_stride-x_offset; 2513bf215546Sopenharmony_ci if (h > dri2_surf->base.Height-y) 2514bf215546Sopenharmony_ci h = dri2_surf->base.Height-y; 2515bf215546Sopenharmony_ci 2516bf215546Sopenharmony_ci for (; h>0; h--) { 2517bf215546Sopenharmony_ci memcpy(dst, src, copy_width); 2518bf215546Sopenharmony_ci src += src_stride; 2519bf215546Sopenharmony_ci dst += dst_stride; 2520bf215546Sopenharmony_ci } 2521bf215546Sopenharmony_ci} 2522bf215546Sopenharmony_ci 2523bf215546Sopenharmony_cistatic void 2524bf215546Sopenharmony_cidri2_wl_swrast_put_image2(__DRIdrawable * draw, int op, 2525bf215546Sopenharmony_ci int x, int y, int w, int h, int stride, 2526bf215546Sopenharmony_ci char *data, void *loaderPrivate) 2527bf215546Sopenharmony_ci{ 2528bf215546Sopenharmony_ci struct dri2_egl_surface *dri2_surf = loaderPrivate; 2529bf215546Sopenharmony_ci int copy_width = dri2_wl_swrast_get_stride_for_format(dri2_surf->format, w); 2530bf215546Sopenharmony_ci int dst_stride = dri2_wl_swrast_get_stride_for_format(dri2_surf->format, dri2_surf->base.Width); 2531bf215546Sopenharmony_ci int x_offset = dri2_wl_swrast_get_stride_for_format(dri2_surf->format, x); 2532bf215546Sopenharmony_ci char *src, *dst; 2533bf215546Sopenharmony_ci 2534bf215546Sopenharmony_ci assert(copy_width <= stride); 2535bf215546Sopenharmony_ci 2536bf215546Sopenharmony_ci (void) swrast_update_buffers(dri2_surf); 2537bf215546Sopenharmony_ci dst = dri2_wl_swrast_get_backbuffer_data(dri2_surf); 2538bf215546Sopenharmony_ci 2539bf215546Sopenharmony_ci /* partial copy, copy old content */ 2540bf215546Sopenharmony_ci if (copy_width < dst_stride) 2541bf215546Sopenharmony_ci dri2_wl_swrast_get_image(draw, 0, 0, 2542bf215546Sopenharmony_ci dri2_surf->base.Width, dri2_surf->base.Height, 2543bf215546Sopenharmony_ci dst, loaderPrivate); 2544bf215546Sopenharmony_ci 2545bf215546Sopenharmony_ci dst += x_offset; 2546bf215546Sopenharmony_ci dst += y * dst_stride; 2547bf215546Sopenharmony_ci 2548bf215546Sopenharmony_ci src = data; 2549bf215546Sopenharmony_ci 2550bf215546Sopenharmony_ci /* drivers expect we do these checks (and some rely on it) */ 2551bf215546Sopenharmony_ci if (copy_width > dst_stride-x_offset) 2552bf215546Sopenharmony_ci copy_width = dst_stride-x_offset; 2553bf215546Sopenharmony_ci if (h > dri2_surf->base.Height-y) 2554bf215546Sopenharmony_ci h = dri2_surf->base.Height-y; 2555bf215546Sopenharmony_ci 2556bf215546Sopenharmony_ci for (; h>0; h--) { 2557bf215546Sopenharmony_ci memcpy(dst, src, copy_width); 2558bf215546Sopenharmony_ci src += stride; 2559bf215546Sopenharmony_ci dst += dst_stride; 2560bf215546Sopenharmony_ci } 2561bf215546Sopenharmony_ci dri2_wl_swrast_commit_backbuffer(dri2_surf); 2562bf215546Sopenharmony_ci} 2563bf215546Sopenharmony_ci 2564bf215546Sopenharmony_cistatic void 2565bf215546Sopenharmony_cidri2_wl_swrast_put_image(__DRIdrawable * draw, int op, 2566bf215546Sopenharmony_ci int x, int y, int w, int h, 2567bf215546Sopenharmony_ci char *data, void *loaderPrivate) 2568bf215546Sopenharmony_ci{ 2569bf215546Sopenharmony_ci struct dri2_egl_surface *dri2_surf = loaderPrivate; 2570bf215546Sopenharmony_ci int stride; 2571bf215546Sopenharmony_ci 2572bf215546Sopenharmony_ci stride = dri2_wl_swrast_get_stride_for_format(dri2_surf->format, w); 2573bf215546Sopenharmony_ci dri2_wl_swrast_put_image2(draw, op, x, y, w, h, 2574bf215546Sopenharmony_ci stride, data, loaderPrivate); 2575bf215546Sopenharmony_ci} 2576bf215546Sopenharmony_ci 2577bf215546Sopenharmony_cistatic EGLBoolean 2578bf215546Sopenharmony_cidri2_wl_swrast_swap_buffers(_EGLDisplay *disp, _EGLSurface *draw) 2579bf215546Sopenharmony_ci{ 2580bf215546Sopenharmony_ci struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2581bf215546Sopenharmony_ci struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw); 2582bf215546Sopenharmony_ci 2583bf215546Sopenharmony_ci if (!dri2_surf->wl_win) 2584bf215546Sopenharmony_ci return _eglError(EGL_BAD_NATIVE_WINDOW, "dri2_swap_buffers"); 2585bf215546Sopenharmony_ci 2586bf215546Sopenharmony_ci dri2_dpy->core->swapBuffers(dri2_surf->dri_drawable); 2587bf215546Sopenharmony_ci if (disp->Options.Zink) { 2588bf215546Sopenharmony_ci dri2_surf->current = dri2_surf->back; 2589bf215546Sopenharmony_ci dri2_surf->back = NULL; 2590bf215546Sopenharmony_ci } 2591bf215546Sopenharmony_ci return EGL_TRUE; 2592bf215546Sopenharmony_ci} 2593bf215546Sopenharmony_ci 2594bf215546Sopenharmony_cistatic void 2595bf215546Sopenharmony_cishm_handle_format(void *data, struct wl_shm *shm, uint32_t format) 2596bf215546Sopenharmony_ci{ 2597bf215546Sopenharmony_ci struct dri2_egl_display *dri2_dpy = data; 2598bf215546Sopenharmony_ci int visual_idx = dri2_wl_visual_idx_from_shm_format(format); 2599bf215546Sopenharmony_ci 2600bf215546Sopenharmony_ci if (visual_idx == -1) 2601bf215546Sopenharmony_ci return; 2602bf215546Sopenharmony_ci 2603bf215546Sopenharmony_ci BITSET_SET(dri2_dpy->formats.formats_bitmap, visual_idx); 2604bf215546Sopenharmony_ci} 2605bf215546Sopenharmony_ci 2606bf215546Sopenharmony_cistatic const struct wl_shm_listener shm_listener = { 2607bf215546Sopenharmony_ci .format = shm_handle_format 2608bf215546Sopenharmony_ci}; 2609bf215546Sopenharmony_ci 2610bf215546Sopenharmony_cistatic void 2611bf215546Sopenharmony_ciregistry_handle_global_swrast(void *data, struct wl_registry *registry, 2612bf215546Sopenharmony_ci uint32_t name, const char *interface, 2613bf215546Sopenharmony_ci uint32_t version) 2614bf215546Sopenharmony_ci{ 2615bf215546Sopenharmony_ci struct dri2_egl_display *dri2_dpy = data; 2616bf215546Sopenharmony_ci 2617bf215546Sopenharmony_ci if (strcmp(interface, "wl_shm") == 0) { 2618bf215546Sopenharmony_ci dri2_dpy->wl_shm = 2619bf215546Sopenharmony_ci wl_registry_bind(registry, name, &wl_shm_interface, 1); 2620bf215546Sopenharmony_ci wl_shm_add_listener(dri2_dpy->wl_shm, &shm_listener, dri2_dpy); 2621bf215546Sopenharmony_ci } 2622bf215546Sopenharmony_ci} 2623bf215546Sopenharmony_ci 2624bf215546Sopenharmony_cistatic const struct wl_registry_listener registry_listener_swrast = { 2625bf215546Sopenharmony_ci .global = registry_handle_global_swrast, 2626bf215546Sopenharmony_ci .global_remove = registry_handle_global_remove 2627bf215546Sopenharmony_ci}; 2628bf215546Sopenharmony_ci 2629bf215546Sopenharmony_cistatic const struct dri2_egl_display_vtbl dri2_wl_swrast_display_vtbl = { 2630bf215546Sopenharmony_ci .authenticate = NULL, 2631bf215546Sopenharmony_ci .create_window_surface = dri2_wl_create_window_surface, 2632bf215546Sopenharmony_ci .create_pixmap_surface = dri2_wl_create_pixmap_surface, 2633bf215546Sopenharmony_ci .destroy_surface = dri2_wl_destroy_surface, 2634bf215546Sopenharmony_ci .create_image = dri2_create_image_khr, 2635bf215546Sopenharmony_ci .swap_buffers = dri2_wl_swrast_swap_buffers, 2636bf215546Sopenharmony_ci .get_dri_drawable = dri2_surface_get_dri_drawable, 2637bf215546Sopenharmony_ci}; 2638bf215546Sopenharmony_ci 2639bf215546Sopenharmony_cistatic const __DRIswrastLoaderExtension swrast_loader_extension = { 2640bf215546Sopenharmony_ci .base = { __DRI_SWRAST_LOADER, 2 }, 2641bf215546Sopenharmony_ci 2642bf215546Sopenharmony_ci .getDrawableInfo = dri2_wl_swrast_get_drawable_info, 2643bf215546Sopenharmony_ci .putImage = dri2_wl_swrast_put_image, 2644bf215546Sopenharmony_ci .getImage = dri2_wl_swrast_get_image, 2645bf215546Sopenharmony_ci .putImage2 = dri2_wl_swrast_put_image2, 2646bf215546Sopenharmony_ci}; 2647bf215546Sopenharmony_ci 2648bf215546Sopenharmony_cistatic void 2649bf215546Sopenharmony_cikopperSetSurfaceCreateInfo(void *_draw, struct kopper_loader_info *out) 2650bf215546Sopenharmony_ci{ 2651bf215546Sopenharmony_ci struct dri2_egl_surface *dri2_surf = _draw; 2652bf215546Sopenharmony_ci struct dri2_egl_display *dri2_dpy = dri2_egl_display(dri2_surf->base.Resource.Display); 2653bf215546Sopenharmony_ci VkWaylandSurfaceCreateInfoKHR *wlsci = &out->wl; 2654bf215546Sopenharmony_ci 2655bf215546Sopenharmony_ci wlsci->sType = VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR; 2656bf215546Sopenharmony_ci wlsci->pNext = NULL; 2657bf215546Sopenharmony_ci wlsci->flags = 0; 2658bf215546Sopenharmony_ci wlsci->display = dri2_dpy->wl_dpy; 2659bf215546Sopenharmony_ci wlsci->surface = dri2_surf->wl_surface_wrapper; 2660bf215546Sopenharmony_ci} 2661bf215546Sopenharmony_ci 2662bf215546Sopenharmony_cistatic const __DRIkopperLoaderExtension kopper_loader_extension = { 2663bf215546Sopenharmony_ci .base = { __DRI_KOPPER_LOADER, 1 }, 2664bf215546Sopenharmony_ci 2665bf215546Sopenharmony_ci .SetSurfaceCreateInfo = kopperSetSurfaceCreateInfo, 2666bf215546Sopenharmony_ci}; 2667bf215546Sopenharmony_cistatic const __DRIextension *swrast_loader_extensions[] = { 2668bf215546Sopenharmony_ci &swrast_loader_extension.base, 2669bf215546Sopenharmony_ci &image_lookup_extension.base, 2670bf215546Sopenharmony_ci &kopper_loader_extension.base, 2671bf215546Sopenharmony_ci NULL, 2672bf215546Sopenharmony_ci}; 2673bf215546Sopenharmony_ci 2674bf215546Sopenharmony_cistatic EGLBoolean 2675bf215546Sopenharmony_cidri2_initialize_wayland_swrast(_EGLDisplay *disp) 2676bf215546Sopenharmony_ci{ 2677bf215546Sopenharmony_ci _EGLDevice *dev; 2678bf215546Sopenharmony_ci struct dri2_egl_display *dri2_dpy; 2679bf215546Sopenharmony_ci 2680bf215546Sopenharmony_ci dri2_dpy = calloc(1, sizeof *dri2_dpy); 2681bf215546Sopenharmony_ci if (!dri2_dpy) 2682bf215546Sopenharmony_ci return _eglError(EGL_BAD_ALLOC, "eglInitialize"); 2683bf215546Sopenharmony_ci 2684bf215546Sopenharmony_ci dri2_dpy->fd = -1; 2685bf215546Sopenharmony_ci disp->DriverData = (void *) dri2_dpy; 2686bf215546Sopenharmony_ci 2687bf215546Sopenharmony_ci if (dri2_wl_formats_init(&dri2_dpy->formats) < 0) 2688bf215546Sopenharmony_ci goto cleanup; 2689bf215546Sopenharmony_ci 2690bf215546Sopenharmony_ci if (disp->PlatformDisplay == NULL) { 2691bf215546Sopenharmony_ci dri2_dpy->wl_dpy = wl_display_connect(NULL); 2692bf215546Sopenharmony_ci if (dri2_dpy->wl_dpy == NULL) 2693bf215546Sopenharmony_ci goto cleanup; 2694bf215546Sopenharmony_ci dri2_dpy->own_device = true; 2695bf215546Sopenharmony_ci } else { 2696bf215546Sopenharmony_ci dri2_dpy->wl_dpy = disp->PlatformDisplay; 2697bf215546Sopenharmony_ci } 2698bf215546Sopenharmony_ci 2699bf215546Sopenharmony_ci dev = _eglAddDevice(dri2_dpy->fd, true); 2700bf215546Sopenharmony_ci if (!dev) { 2701bf215546Sopenharmony_ci _eglError(EGL_NOT_INITIALIZED, "DRI2: failed to find EGLDevice"); 2702bf215546Sopenharmony_ci goto cleanup; 2703bf215546Sopenharmony_ci } 2704bf215546Sopenharmony_ci 2705bf215546Sopenharmony_ci disp->Device = dev; 2706bf215546Sopenharmony_ci 2707bf215546Sopenharmony_ci dri2_dpy->wl_queue = wl_display_create_queue(dri2_dpy->wl_dpy); 2708bf215546Sopenharmony_ci 2709bf215546Sopenharmony_ci dri2_dpy->wl_dpy_wrapper = wl_proxy_create_wrapper(dri2_dpy->wl_dpy); 2710bf215546Sopenharmony_ci if (dri2_dpy->wl_dpy_wrapper == NULL) 2711bf215546Sopenharmony_ci goto cleanup; 2712bf215546Sopenharmony_ci 2713bf215546Sopenharmony_ci wl_proxy_set_queue((struct wl_proxy *) dri2_dpy->wl_dpy_wrapper, 2714bf215546Sopenharmony_ci dri2_dpy->wl_queue); 2715bf215546Sopenharmony_ci 2716bf215546Sopenharmony_ci if (dri2_dpy->own_device) 2717bf215546Sopenharmony_ci wl_display_dispatch_pending(dri2_dpy->wl_dpy); 2718bf215546Sopenharmony_ci 2719bf215546Sopenharmony_ci dri2_dpy->wl_registry = wl_display_get_registry(dri2_dpy->wl_dpy_wrapper); 2720bf215546Sopenharmony_ci wl_registry_add_listener(dri2_dpy->wl_registry, 2721bf215546Sopenharmony_ci ®istry_listener_swrast, dri2_dpy); 2722bf215546Sopenharmony_ci 2723bf215546Sopenharmony_ci if (roundtrip(dri2_dpy) < 0 || dri2_dpy->wl_shm == NULL) 2724bf215546Sopenharmony_ci goto cleanup; 2725bf215546Sopenharmony_ci 2726bf215546Sopenharmony_ci if (roundtrip(dri2_dpy) < 0 || !BITSET_TEST_RANGE(dri2_dpy->formats.formats_bitmap, 2727bf215546Sopenharmony_ci 0, dri2_dpy->formats.num_formats)) 2728bf215546Sopenharmony_ci goto cleanup; 2729bf215546Sopenharmony_ci 2730bf215546Sopenharmony_ci dri2_dpy->driver_name = strdup(disp->Options.Zink ? "zink" : "swrast"); 2731bf215546Sopenharmony_ci if (!dri2_load_driver_swrast(disp)) 2732bf215546Sopenharmony_ci goto cleanup; 2733bf215546Sopenharmony_ci 2734bf215546Sopenharmony_ci dri2_dpy->loader_extensions = swrast_loader_extensions; 2735bf215546Sopenharmony_ci 2736bf215546Sopenharmony_ci if (!dri2_create_screen(disp)) 2737bf215546Sopenharmony_ci goto cleanup; 2738bf215546Sopenharmony_ci 2739bf215546Sopenharmony_ci if (!dri2_setup_extensions(disp)) 2740bf215546Sopenharmony_ci goto cleanup; 2741bf215546Sopenharmony_ci 2742bf215546Sopenharmony_ci dri2_setup_screen(disp); 2743bf215546Sopenharmony_ci 2744bf215546Sopenharmony_ci dri2_wl_setup_swap_interval(disp); 2745bf215546Sopenharmony_ci 2746bf215546Sopenharmony_ci if (!dri2_wl_add_configs_for_visuals(disp)) { 2747bf215546Sopenharmony_ci _eglError(EGL_NOT_INITIALIZED, "DRI2: failed to add configs"); 2748bf215546Sopenharmony_ci goto cleanup; 2749bf215546Sopenharmony_ci } 2750bf215546Sopenharmony_ci 2751bf215546Sopenharmony_ci /* Fill vtbl last to prevent accidentally calling virtual function during 2752bf215546Sopenharmony_ci * initialization. 2753bf215546Sopenharmony_ci */ 2754bf215546Sopenharmony_ci dri2_dpy->vtbl = &dri2_wl_swrast_display_vtbl; 2755bf215546Sopenharmony_ci 2756bf215546Sopenharmony_ci return EGL_TRUE; 2757bf215546Sopenharmony_ci 2758bf215546Sopenharmony_ci cleanup: 2759bf215546Sopenharmony_ci dri2_display_destroy(disp); 2760bf215546Sopenharmony_ci return EGL_FALSE; 2761bf215546Sopenharmony_ci} 2762bf215546Sopenharmony_ci 2763bf215546Sopenharmony_ciEGLBoolean 2764bf215546Sopenharmony_cidri2_initialize_wayland(_EGLDisplay *disp) 2765bf215546Sopenharmony_ci{ 2766bf215546Sopenharmony_ci if (disp->Options.ForceSoftware) 2767bf215546Sopenharmony_ci return dri2_initialize_wayland_swrast(disp); 2768bf215546Sopenharmony_ci else 2769bf215546Sopenharmony_ci return dri2_initialize_wayland_drm(disp); 2770bf215546Sopenharmony_ci} 2771bf215546Sopenharmony_ci 2772bf215546Sopenharmony_civoid 2773bf215546Sopenharmony_cidri2_teardown_wayland(struct dri2_egl_display *dri2_dpy) 2774bf215546Sopenharmony_ci{ 2775bf215546Sopenharmony_ci dri2_wl_formats_fini(&dri2_dpy->formats); 2776bf215546Sopenharmony_ci if (dri2_dpy->wl_drm) 2777bf215546Sopenharmony_ci wl_drm_destroy(dri2_dpy->wl_drm); 2778bf215546Sopenharmony_ci if (dri2_dpy->wl_dmabuf) 2779bf215546Sopenharmony_ci zwp_linux_dmabuf_v1_destroy(dri2_dpy->wl_dmabuf); 2780bf215546Sopenharmony_ci if (dri2_dpy->wl_shm) 2781bf215546Sopenharmony_ci wl_shm_destroy(dri2_dpy->wl_shm); 2782bf215546Sopenharmony_ci if (dri2_dpy->wl_registry) 2783bf215546Sopenharmony_ci wl_registry_destroy(dri2_dpy->wl_registry); 2784bf215546Sopenharmony_ci if (dri2_dpy->wl_queue) 2785bf215546Sopenharmony_ci wl_event_queue_destroy(dri2_dpy->wl_queue); 2786bf215546Sopenharmony_ci if (dri2_dpy->wl_dpy_wrapper) 2787bf215546Sopenharmony_ci wl_proxy_wrapper_destroy(dri2_dpy->wl_dpy_wrapper); 2788bf215546Sopenharmony_ci 2789bf215546Sopenharmony_ci if (dri2_dpy->own_device) 2790bf215546Sopenharmony_ci wl_display_disconnect(dri2_dpy->wl_dpy); 2791bf215546Sopenharmony_ci} 2792