1848b8605Smrg/* 2848b8605Smrg * Copyright © 2010 Intel Corporation 3848b8605Smrg * 4848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5848b8605Smrg * copy of this software and associated documentation files (the "Software"), 6848b8605Smrg * to deal in the Software without restriction, including without limitation 7848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the 9848b8605Smrg * Software is furnished to do so, subject to the following conditions: 10848b8605Smrg * 11848b8605Smrg * The above copyright notice and this permission notice (including the next 12848b8605Smrg * paragraph) shall be included in all copies or substantial portions of the 13848b8605Smrg * Software. 14848b8605Smrg * 15848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16848b8605Smrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17848b8605Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18848b8605Smrg * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19848b8605Smrg * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20848b8605Smrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21848b8605Smrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22848b8605Smrg * DEALINGS IN THE SOFTWARE. 23848b8605Smrg * 24848b8605Smrg * Authors: 25848b8605Smrg * Kristian Høgsberg <krh@bitplanet.net> 26848b8605Smrg */ 27848b8605Smrg 28b8e80941Smrg#include <stdbool.h> 29b8e80941Smrg#include <stdint.h> 30b8e80941Smrg#include <stdbool.h> 31848b8605Smrg#include <stdlib.h> 32848b8605Smrg#include <string.h> 33848b8605Smrg#include <stdio.h> 34848b8605Smrg#include <limits.h> 35848b8605Smrg#include <dlfcn.h> 36848b8605Smrg#include <fcntl.h> 37848b8605Smrg#include <errno.h> 38848b8605Smrg#include <unistd.h> 39b8e80941Smrg#include <c11/threads.h> 40b8e80941Smrg#include <time.h> 41848b8605Smrg#ifdef HAVE_LIBDRM 42848b8605Smrg#include <xf86drm.h> 43b8e80941Smrg#include "drm-uapi/drm_fourcc.h" 44848b8605Smrg#endif 45848b8605Smrg#include <GL/gl.h> 46848b8605Smrg#include <GL/internal/dri_interface.h> 47848b8605Smrg#include <sys/types.h> 48848b8605Smrg#include <sys/stat.h> 49848b8605Smrg 50848b8605Smrg#ifdef HAVE_WAYLAND_PLATFORM 51b8e80941Smrg#include <wayland-client.h> 52848b8605Smrg#include "wayland-drm.h" 53848b8605Smrg#include "wayland-drm-client-protocol.h" 54b8e80941Smrg#include "linux-dmabuf-unstable-v1-client-protocol.h" 55b8e80941Smrg#endif 56b8e80941Smrg 57b8e80941Smrg#ifdef HAVE_X11_PLATFORM 58b8e80941Smrg#include "X11/Xlibint.h" 59848b8605Smrg#endif 60848b8605Smrg 61b8e80941Smrg#include "egldefines.h" 62848b8605Smrg#include "egl_dri2.h" 63b8e80941Smrg#include "GL/mesa_glinterop.h" 64b8e80941Smrg#include "loader/loader.h" 65b8e80941Smrg#include "util/u_atomic.h" 66b8e80941Smrg#include "util/u_vector.h" 67b8e80941Smrg#include "mapi/glapi/glapi.h" 68b8e80941Smrg 69b8e80941Smrg/* Additional definitions not yet in the drm_fourcc.h. 70b8e80941Smrg */ 71b8e80941Smrg#ifndef DRM_FORMAT_P010 72b8e80941Smrg#define DRM_FORMAT_P010 fourcc_code('P', '0', '1', '0') /* 2x2 subsampled Cb:Cr plane 10 bits per channel */ 73b8e80941Smrg#endif 74b8e80941Smrg 75b8e80941Smrg#ifndef DRM_FORMAT_P012 76b8e80941Smrg#define DRM_FORMAT_P012 fourcc_code('P', '0', '1', '2') /* 2x2 subsampled Cb:Cr plane 12 bits per channel */ 77b8e80941Smrg#endif 78b8e80941Smrg 79b8e80941Smrg#ifndef DRM_FORMAT_P016 80b8e80941Smrg#define DRM_FORMAT_P016 fourcc_code('P', '0', '1', '6') /* 2x2 subsampled Cb:Cr plane 16 bits per channel */ 81b8e80941Smrg#endif 82b8e80941Smrg 83b8e80941Smrg#define NUM_ATTRIBS 12 84b8e80941Smrg 85b8e80941Smrgstatic void 86b8e80941Smrgdri_set_background_context(void *loaderPrivate) 87b8e80941Smrg{ 88b8e80941Smrg _EGLContext *ctx = _eglGetCurrentContext(); 89b8e80941Smrg _EGLThreadInfo *t = _eglGetCurrentThread(); 90b8e80941Smrg 91b8e80941Smrg _eglBindContextToThread(ctx, t); 92b8e80941Smrg} 93b8e80941Smrg 94b8e80941Smrgstatic void 95b8e80941Smrgdri2_gl_flush() 96b8e80941Smrg{ 97b8e80941Smrg static void (*glFlush)(void); 98b8e80941Smrg static mtx_t glFlushMutex = _MTX_INITIALIZER_NP; 99b8e80941Smrg 100b8e80941Smrg mtx_lock(&glFlushMutex); 101b8e80941Smrg if (!glFlush) 102b8e80941Smrg glFlush = _glapi_get_proc_address("glFlush"); 103b8e80941Smrg mtx_unlock(&glFlushMutex); 104b8e80941Smrg 105b8e80941Smrg /* if glFlush is not available things are horribly broken */ 106b8e80941Smrg if (!glFlush) { 107b8e80941Smrg _eglLog(_EGL_WARNING, "DRI2: failed to find glFlush entry point"); 108b8e80941Smrg return; 109b8e80941Smrg } 110b8e80941Smrg 111b8e80941Smrg glFlush(); 112b8e80941Smrg} 113b8e80941Smrg 114b8e80941Smrgstatic GLboolean 115b8e80941Smrgdri_is_thread_safe(void *loaderPrivate) 116b8e80941Smrg{ 117b8e80941Smrg struct dri2_egl_surface *dri2_surf = loaderPrivate; 118b8e80941Smrg MAYBE_UNUSED _EGLDisplay *display = dri2_surf->base.Resource.Display; 119b8e80941Smrg 120b8e80941Smrg#ifdef HAVE_X11_PLATFORM 121b8e80941Smrg Display *xdpy = (Display*)display->PlatformDisplay; 122b8e80941Smrg 123b8e80941Smrg /* Check Xlib is running in thread safe mode when running on EGL/X11-xlib 124b8e80941Smrg * platform 125b8e80941Smrg * 126b8e80941Smrg * 'lock_fns' is the XLockDisplay function pointer of the X11 display 'dpy'. 127b8e80941Smrg * It wll be NULL if XInitThreads wasn't called. 128b8e80941Smrg */ 129b8e80941Smrg if (display->Platform == _EGL_PLATFORM_X11 && xdpy && !xdpy->lock_fns) 130b8e80941Smrg return false; 131b8e80941Smrg#endif 132b8e80941Smrg 133b8e80941Smrg#ifdef HAVE_WAYLAND_PLATFORM 134b8e80941Smrg if (display->Platform == _EGL_PLATFORM_WAYLAND) 135b8e80941Smrg return true; 136b8e80941Smrg#endif 137b8e80941Smrg 138b8e80941Smrg return true; 139b8e80941Smrg} 140b8e80941Smrg 141b8e80941Smrgconst __DRIbackgroundCallableExtension background_callable_extension = { 142b8e80941Smrg .base = { __DRI_BACKGROUND_CALLABLE, 2 }, 143b8e80941Smrg 144b8e80941Smrg .setBackgroundContext = dri_set_background_context, 145b8e80941Smrg .isThreadSafe = dri_is_thread_safe, 146b8e80941Smrg}; 147848b8605Smrg 148848b8605Smrgconst __DRIuseInvalidateExtension use_invalidate = { 149848b8605Smrg .base = { __DRI_USE_INVALIDATE, 1 } 150848b8605Smrg}; 151848b8605Smrg 152b8e80941Smrgstatic const EGLint dri2_to_egl_attribute_map[__DRI_ATTRIB_MAX] = { 153b8e80941Smrg [__DRI_ATTRIB_BUFFER_SIZE ] = EGL_BUFFER_SIZE, 154b8e80941Smrg [__DRI_ATTRIB_LEVEL] = EGL_LEVEL, 155b8e80941Smrg [__DRI_ATTRIB_RED_SIZE] = EGL_RED_SIZE, 156b8e80941Smrg [__DRI_ATTRIB_GREEN_SIZE] = EGL_GREEN_SIZE, 157b8e80941Smrg [__DRI_ATTRIB_BLUE_SIZE] = EGL_BLUE_SIZE, 158b8e80941Smrg [__DRI_ATTRIB_LUMINANCE_SIZE] = EGL_LUMINANCE_SIZE, 159b8e80941Smrg [__DRI_ATTRIB_ALPHA_SIZE] = EGL_ALPHA_SIZE, 160b8e80941Smrg [__DRI_ATTRIB_DEPTH_SIZE] = EGL_DEPTH_SIZE, 161b8e80941Smrg [__DRI_ATTRIB_STENCIL_SIZE] = EGL_STENCIL_SIZE, 162b8e80941Smrg [__DRI_ATTRIB_SAMPLE_BUFFERS] = EGL_SAMPLE_BUFFERS, 163b8e80941Smrg [__DRI_ATTRIB_SAMPLES] = EGL_SAMPLES, 164b8e80941Smrg [__DRI_ATTRIB_MAX_PBUFFER_WIDTH] = EGL_MAX_PBUFFER_WIDTH, 165b8e80941Smrg [__DRI_ATTRIB_MAX_PBUFFER_HEIGHT] = EGL_MAX_PBUFFER_HEIGHT, 166b8e80941Smrg [__DRI_ATTRIB_MAX_PBUFFER_PIXELS] = EGL_MAX_PBUFFER_PIXELS, 167b8e80941Smrg [__DRI_ATTRIB_MAX_SWAP_INTERVAL] = EGL_MAX_SWAP_INTERVAL, 168b8e80941Smrg [__DRI_ATTRIB_MIN_SWAP_INTERVAL] = EGL_MIN_SWAP_INTERVAL, 169b8e80941Smrg [__DRI_ATTRIB_YINVERTED] = EGL_Y_INVERTED_NOK, 170848b8605Smrg}; 171848b8605Smrg 172b8e80941Smrgconst __DRIconfig * 173b8e80941Smrgdri2_get_dri_config(struct dri2_egl_config *conf, EGLint surface_type, 174b8e80941Smrg EGLenum colorspace) 175b8e80941Smrg{ 176b8e80941Smrg const bool double_buffer = surface_type == EGL_WINDOW_BIT; 177b8e80941Smrg const bool srgb = colorspace == EGL_GL_COLORSPACE_SRGB_KHR; 178b8e80941Smrg 179b8e80941Smrg return conf->dri_config[double_buffer][srgb]; 180b8e80941Smrg} 181b8e80941Smrg 182848b8605Smrgstatic EGLBoolean 183848b8605Smrgdri2_match_config(const _EGLConfig *conf, const _EGLConfig *criteria) 184848b8605Smrg{ 185848b8605Smrg if (_eglCompareConfigs(conf, criteria, NULL, EGL_FALSE) != 0) 186848b8605Smrg return EGL_FALSE; 187848b8605Smrg 188848b8605Smrg if (!_eglMatchConfig(conf, criteria)) 189848b8605Smrg return EGL_FALSE; 190848b8605Smrg 191848b8605Smrg return EGL_TRUE; 192848b8605Smrg} 193848b8605Smrg 194848b8605Smrgstruct dri2_egl_config * 195848b8605Smrgdri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id, 196b8e80941Smrg EGLint surface_type, const EGLint *attr_list, 197b8e80941Smrg const unsigned int *rgba_masks) 198848b8605Smrg{ 199848b8605Smrg struct dri2_egl_config *conf; 200b8e80941Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 201848b8605Smrg _EGLConfig base; 202848b8605Smrg unsigned int attrib, value, double_buffer; 203b8e80941Smrg bool srgb = false; 204848b8605Smrg EGLint key, bind_to_texture_rgb, bind_to_texture_rgba; 205848b8605Smrg unsigned int dri_masks[4] = { 0, 0, 0, 0 }; 206848b8605Smrg _EGLConfig *matching_config; 207848b8605Smrg EGLint num_configs = 0; 208848b8605Smrg EGLint config_id; 209848b8605Smrg 210848b8605Smrg _eglInitConfig(&base, disp, id); 211b8e80941Smrg 212848b8605Smrg double_buffer = 0; 213848b8605Smrg bind_to_texture_rgb = 0; 214848b8605Smrg bind_to_texture_rgba = 0; 215848b8605Smrg 216b8e80941Smrg for (int i = 0; i < __DRI_ATTRIB_MAX; ++i) { 217b8e80941Smrg if (!dri2_dpy->core->indexConfigAttrib(dri_config, i, &attrib, &value)) 218b8e80941Smrg break; 219b8e80941Smrg 220848b8605Smrg switch (attrib) { 221848b8605Smrg case __DRI_ATTRIB_RENDER_TYPE: 222b8e80941Smrg if (value & __DRI_ATTRIB_RGBA_BIT) 223b8e80941Smrg value = EGL_RGB_BUFFER; 224b8e80941Smrg else if (value & __DRI_ATTRIB_LUMINANCE_BIT) 225b8e80941Smrg value = EGL_LUMINANCE_BUFFER; 226b8e80941Smrg else 227b8e80941Smrg return NULL; 228b8e80941Smrg _eglSetConfigKey(&base, EGL_COLOR_BUFFER_TYPE, value); 229b8e80941Smrg break; 230848b8605Smrg 231848b8605Smrg case __DRI_ATTRIB_CONFIG_CAVEAT: 232848b8605Smrg if (value & __DRI_ATTRIB_NON_CONFORMANT_CONFIG) 233848b8605Smrg value = EGL_NON_CONFORMANT_CONFIG; 234848b8605Smrg else if (value & __DRI_ATTRIB_SLOW_BIT) 235848b8605Smrg value = EGL_SLOW_CONFIG; 236b8e80941Smrg else 237b8e80941Smrg value = EGL_NONE; 238b8e80941Smrg _eglSetConfigKey(&base, EGL_CONFIG_CAVEAT, value); 239848b8605Smrg break; 240848b8605Smrg 241848b8605Smrg case __DRI_ATTRIB_BIND_TO_TEXTURE_RGB: 242b8e80941Smrg bind_to_texture_rgb = value; 243b8e80941Smrg break; 244848b8605Smrg 245848b8605Smrg case __DRI_ATTRIB_BIND_TO_TEXTURE_RGBA: 246b8e80941Smrg bind_to_texture_rgba = value; 247b8e80941Smrg break; 248848b8605Smrg 249848b8605Smrg case __DRI_ATTRIB_DOUBLE_BUFFER: 250b8e80941Smrg double_buffer = value; 251b8e80941Smrg break; 252848b8605Smrg 253848b8605Smrg case __DRI_ATTRIB_RED_MASK: 254848b8605Smrg dri_masks[0] = value; 255848b8605Smrg break; 256848b8605Smrg 257848b8605Smrg case __DRI_ATTRIB_GREEN_MASK: 258848b8605Smrg dri_masks[1] = value; 259848b8605Smrg break; 260848b8605Smrg 261848b8605Smrg case __DRI_ATTRIB_BLUE_MASK: 262848b8605Smrg dri_masks[2] = value; 263848b8605Smrg break; 264848b8605Smrg 265848b8605Smrg case __DRI_ATTRIB_ALPHA_MASK: 266848b8605Smrg dri_masks[3] = value; 267848b8605Smrg break; 268848b8605Smrg 269b8e80941Smrg case __DRI_ATTRIB_ACCUM_RED_SIZE: 270b8e80941Smrg case __DRI_ATTRIB_ACCUM_GREEN_SIZE: 271b8e80941Smrg case __DRI_ATTRIB_ACCUM_BLUE_SIZE: 272b8e80941Smrg case __DRI_ATTRIB_ACCUM_ALPHA_SIZE: 273b8e80941Smrg /* Don't expose visuals with the accumulation buffer. */ 274b8e80941Smrg if (value > 0) 275b8e80941Smrg return NULL; 276b8e80941Smrg break; 277b8e80941Smrg 278b8e80941Smrg case __DRI_ATTRIB_FRAMEBUFFER_SRGB_CAPABLE: 279b8e80941Smrg srgb = value != 0; 280b8e80941Smrg if (!disp->Extensions.KHR_gl_colorspace && srgb) 281b8e80941Smrg return NULL; 282b8e80941Smrg break; 283b8e80941Smrg 284b8e80941Smrg case __DRI_ATTRIB_MAX_PBUFFER_WIDTH: 285b8e80941Smrg _eglSetConfigKey(&base, EGL_MAX_PBUFFER_WIDTH, 286b8e80941Smrg _EGL_MAX_PBUFFER_WIDTH); 287b8e80941Smrg break; 288b8e80941Smrg case __DRI_ATTRIB_MAX_PBUFFER_HEIGHT: 289b8e80941Smrg _eglSetConfigKey(&base, EGL_MAX_PBUFFER_HEIGHT, 290b8e80941Smrg _EGL_MAX_PBUFFER_HEIGHT); 291b8e80941Smrg break; 292b8e80941Smrg case __DRI_ATTRIB_MUTABLE_RENDER_BUFFER: 293b8e80941Smrg if (disp->Extensions.KHR_mutable_render_buffer) 294b8e80941Smrg surface_type |= EGL_MUTABLE_RENDER_BUFFER_BIT_KHR; 295b8e80941Smrg break; 296848b8605Smrg default: 297b8e80941Smrg key = dri2_to_egl_attribute_map[attrib]; 298b8e80941Smrg if (key != 0) 299b8e80941Smrg _eglSetConfigKey(&base, key, value); 300b8e80941Smrg break; 301848b8605Smrg } 302848b8605Smrg } 303848b8605Smrg 304848b8605Smrg if (attr_list) 305b8e80941Smrg for (int i = 0; attr_list[i] != EGL_NONE; i += 2) 306848b8605Smrg _eglSetConfigKey(&base, attr_list[i], attr_list[i+1]); 307848b8605Smrg 308848b8605Smrg if (rgba_masks && memcmp(rgba_masks, dri_masks, sizeof(dri_masks))) 309848b8605Smrg return NULL; 310848b8605Smrg 311848b8605Smrg base.NativeRenderable = EGL_TRUE; 312848b8605Smrg 313848b8605Smrg base.SurfaceType = surface_type; 314848b8605Smrg if (surface_type & (EGL_PBUFFER_BIT | 315848b8605Smrg (disp->Extensions.NOK_texture_from_pixmap ? EGL_PIXMAP_BIT : 0))) { 316848b8605Smrg base.BindToTextureRGB = bind_to_texture_rgb; 317848b8605Smrg if (base.AlphaSize > 0) 318848b8605Smrg base.BindToTextureRGBA = bind_to_texture_rgba; 319848b8605Smrg } 320848b8605Smrg 321848b8605Smrg base.RenderableType = disp->ClientAPIs; 322848b8605Smrg base.Conformant = disp->ClientAPIs; 323848b8605Smrg 324848b8605Smrg base.MinSwapInterval = dri2_dpy->min_swap_interval; 325848b8605Smrg base.MaxSwapInterval = dri2_dpy->max_swap_interval; 326848b8605Smrg 327848b8605Smrg if (!_eglValidateConfig(&base, EGL_FALSE)) { 328848b8605Smrg _eglLog(_EGL_DEBUG, "DRI2: failed to validate config %d", id); 329848b8605Smrg return NULL; 330848b8605Smrg } 331848b8605Smrg 332848b8605Smrg config_id = base.ConfigID; 333848b8605Smrg base.ConfigID = EGL_DONT_CARE; 334848b8605Smrg base.SurfaceType = EGL_DONT_CARE; 335848b8605Smrg num_configs = _eglFilterArray(disp->Configs, (void **) &matching_config, 1, 336848b8605Smrg (_EGLArrayForEach) dri2_match_config, &base); 337848b8605Smrg 338848b8605Smrg if (num_configs == 1) { 339848b8605Smrg conf = (struct dri2_egl_config *) matching_config; 340848b8605Smrg 341b8e80941Smrg if (!conf->dri_config[double_buffer][srgb]) 342b8e80941Smrg conf->dri_config[double_buffer][srgb] = dri_config; 343848b8605Smrg else 344848b8605Smrg /* a similar config type is already added (unlikely) => discard */ 345848b8605Smrg return NULL; 346848b8605Smrg } 347848b8605Smrg else if (num_configs == 0) { 348b8e80941Smrg conf = calloc(1, sizeof *conf); 349848b8605Smrg if (conf == NULL) 350848b8605Smrg return NULL; 351848b8605Smrg 352b8e80941Smrg conf->dri_config[double_buffer][srgb] = dri_config; 353b8e80941Smrg 354848b8605Smrg memcpy(&conf->base, &base, sizeof base); 355848b8605Smrg conf->base.SurfaceType = 0; 356848b8605Smrg conf->base.ConfigID = config_id; 357848b8605Smrg 358848b8605Smrg _eglLinkConfig(&conf->base); 359848b8605Smrg } 360848b8605Smrg else { 361b8e80941Smrg unreachable("duplicates should not be possible"); 362848b8605Smrg return NULL; 363848b8605Smrg } 364848b8605Smrg 365848b8605Smrg if (double_buffer) { 366848b8605Smrg surface_type &= ~EGL_PIXMAP_BIT; 367848b8605Smrg } 368848b8605Smrg 369b8e80941Smrg /* No support for pbuffer + MSAA for now. 370b8e80941Smrg * 371b8e80941Smrg * XXX TODO: pbuffer + MSAA does not work and causes crashes. 372b8e80941Smrg * See QT bugreport: https://bugreports.qt.io/browse/QTBUG-47509 373b8e80941Smrg */ 374b8e80941Smrg if (base.Samples) { 375b8e80941Smrg surface_type &= ~EGL_PBUFFER_BIT; 376b8e80941Smrg } 377b8e80941Smrg 378848b8605Smrg conf->base.SurfaceType |= surface_type; 379848b8605Smrg 380848b8605Smrg return conf; 381848b8605Smrg} 382848b8605Smrg 383848b8605Smrg__DRIimage * 384848b8605Smrgdri2_lookup_egl_image(__DRIscreen *screen, void *image, void *data) 385848b8605Smrg{ 386848b8605Smrg _EGLDisplay *disp = data; 387848b8605Smrg struct dri2_egl_image *dri2_img; 388848b8605Smrg _EGLImage *img; 389848b8605Smrg 390848b8605Smrg (void) screen; 391848b8605Smrg 392848b8605Smrg img = _eglLookupImage(image, disp); 393848b8605Smrg if (img == NULL) { 394848b8605Smrg _eglError(EGL_BAD_PARAMETER, "dri2_lookup_egl_image"); 395848b8605Smrg return NULL; 396848b8605Smrg } 397848b8605Smrg 398848b8605Smrg dri2_img = dri2_egl_image(image); 399848b8605Smrg 400848b8605Smrg return dri2_img->dri_image; 401848b8605Smrg} 402848b8605Smrg 403848b8605Smrgconst __DRIimageLookupExtension image_lookup_extension = { 404848b8605Smrg .base = { __DRI_IMAGE_LOOKUP, 1 }, 405848b8605Smrg 406848b8605Smrg .lookupEGLImage = dri2_lookup_egl_image 407848b8605Smrg}; 408848b8605Smrg 409848b8605Smrgstruct dri2_extension_match { 410848b8605Smrg const char *name; 411848b8605Smrg int version; 412848b8605Smrg int offset; 413848b8605Smrg}; 414848b8605Smrg 415b8e80941Smrgstatic const struct dri2_extension_match dri3_driver_extensions[] = { 416b8e80941Smrg { __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) }, 417b8e80941Smrg { __DRI_IMAGE_DRIVER, 1, offsetof(struct dri2_egl_display, image_driver) }, 418b8e80941Smrg { NULL, 0, 0 } 419b8e80941Smrg}; 420b8e80941Smrg 421b8e80941Smrgstatic const struct dri2_extension_match dri2_driver_extensions[] = { 422848b8605Smrg { __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) }, 423848b8605Smrg { __DRI_DRI2, 2, offsetof(struct dri2_egl_display, dri2) }, 424848b8605Smrg { NULL, 0, 0 } 425848b8605Smrg}; 426848b8605Smrg 427b8e80941Smrgstatic const struct dri2_extension_match dri2_core_extensions[] = { 428848b8605Smrg { __DRI2_FLUSH, 1, offsetof(struct dri2_egl_display, flush) }, 429848b8605Smrg { __DRI_TEX_BUFFER, 2, offsetof(struct dri2_egl_display, tex_buffer) }, 430848b8605Smrg { __DRI_IMAGE, 1, offsetof(struct dri2_egl_display, image) }, 431848b8605Smrg { NULL, 0, 0 } 432848b8605Smrg}; 433848b8605Smrg 434b8e80941Smrgstatic const struct dri2_extension_match swrast_driver_extensions[] = { 435848b8605Smrg { __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) }, 436848b8605Smrg { __DRI_SWRAST, 2, offsetof(struct dri2_egl_display, swrast) }, 437848b8605Smrg { NULL, 0, 0 } 438848b8605Smrg}; 439848b8605Smrg 440b8e80941Smrgstatic const struct dri2_extension_match swrast_core_extensions[] = { 441848b8605Smrg { __DRI_TEX_BUFFER, 2, offsetof(struct dri2_egl_display, tex_buffer) }, 442848b8605Smrg { NULL, 0, 0 } 443848b8605Smrg}; 444848b8605Smrg 445b8e80941Smrgstatic const struct dri2_extension_match optional_driver_extensions[] = { 446b8e80941Smrg { __DRI_CONFIG_OPTIONS, 1, offsetof(struct dri2_egl_display, configOptions) }, 447b8e80941Smrg { NULL, 0, 0 } 448b8e80941Smrg}; 449b8e80941Smrg 450b8e80941Smrgstatic const struct dri2_extension_match optional_core_extensions[] = { 451b8e80941Smrg { __DRI2_ROBUSTNESS, 1, offsetof(struct dri2_egl_display, robustness) }, 452b8e80941Smrg { __DRI2_NO_ERROR, 1, offsetof(struct dri2_egl_display, no_error) }, 453b8e80941Smrg { __DRI2_CONFIG_QUERY, 1, offsetof(struct dri2_egl_display, config) }, 454b8e80941Smrg { __DRI2_FENCE, 1, offsetof(struct dri2_egl_display, fence) }, 455b8e80941Smrg { __DRI2_RENDERER_QUERY, 1, offsetof(struct dri2_egl_display, rendererQuery) }, 456b8e80941Smrg { __DRI2_INTEROP, 1, offsetof(struct dri2_egl_display, interop) }, 457b8e80941Smrg { __DRI_IMAGE, 1, offsetof(struct dri2_egl_display, image) }, 458b8e80941Smrg { __DRI2_FLUSH_CONTROL, 1, offsetof(struct dri2_egl_display, flush_control) }, 459b8e80941Smrg { __DRI2_BLOB, 1, offsetof(struct dri2_egl_display, blob) }, 460b8e80941Smrg { __DRI_MUTABLE_RENDER_BUFFER_DRIVER, 1, offsetof(struct dri2_egl_display, mutable_render_buffer) }, 461b8e80941Smrg { NULL, 0, 0 } 462b8e80941Smrg}; 463b8e80941Smrg 464848b8605Smrgstatic EGLBoolean 465848b8605Smrgdri2_bind_extensions(struct dri2_egl_display *dri2_dpy, 466b8e80941Smrg const struct dri2_extension_match *matches, 467b8e80941Smrg const __DRIextension **extensions, 468b8e80941Smrg bool optional) 469848b8605Smrg{ 470b8e80941Smrg int ret = EGL_TRUE; 471848b8605Smrg void *field; 472848b8605Smrg 473b8e80941Smrg for (int i = 0; extensions[i]; i++) { 474b8e80941Smrg _eglLog(_EGL_DEBUG, "found extension `%s'", extensions[i]->name); 475b8e80941Smrg for (int j = 0; matches[j].name; j++) { 476b8e80941Smrg if (strcmp(extensions[i]->name, matches[j].name) == 0 && 477b8e80941Smrg extensions[i]->version >= matches[j].version) { 478b8e80941Smrg field = ((char *) dri2_dpy + matches[j].offset); 479b8e80941Smrg *(const __DRIextension **) field = extensions[i]; 480b8e80941Smrg _eglLog(_EGL_INFO, "found extension %s version %d", 481b8e80941Smrg extensions[i]->name, extensions[i]->version); 482b8e80941Smrg break; 483b8e80941Smrg } 484848b8605Smrg } 485848b8605Smrg } 486b8e80941Smrg 487b8e80941Smrg for (int j = 0; matches[j].name; j++) { 488848b8605Smrg field = ((char *) dri2_dpy + matches[j].offset); 489848b8605Smrg if (*(const __DRIextension **) field == NULL) { 490b8e80941Smrg if (optional) { 491b8e80941Smrg _eglLog(_EGL_DEBUG, "did not find optional extension %s version %d", 492b8e80941Smrg matches[j].name, matches[j].version); 493b8e80941Smrg } else { 494b8e80941Smrg _eglLog(_EGL_WARNING, "did not find extension %s version %d", 495b8e80941Smrg matches[j].name, matches[j].version); 496b8e80941Smrg ret = EGL_FALSE; 497b8e80941Smrg } 498848b8605Smrg } 499848b8605Smrg } 500848b8605Smrg 501848b8605Smrg return ret; 502848b8605Smrg} 503848b8605Smrg 504848b8605Smrgstatic const __DRIextension ** 505848b8605Smrgdri2_open_driver(_EGLDisplay *disp) 506848b8605Smrg{ 507b8e80941Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 508b8e80941Smrg static const char *search_path_vars[] = { 509b8e80941Smrg "LIBGL_DRIVERS_PATH", 510b8e80941Smrg NULL, 511b8e80941Smrg }; 512b8e80941Smrg 513b8e80941Smrg return loader_open_driver(dri2_dpy->driver_name, 514b8e80941Smrg &dri2_dpy->driver, 515b8e80941Smrg search_path_vars); 516848b8605Smrg} 517848b8605Smrg 518b8e80941Smrgstatic EGLBoolean 519b8e80941Smrgdri2_load_driver_common(_EGLDisplay *disp, 520b8e80941Smrg const struct dri2_extension_match *driver_extensions) 521848b8605Smrg{ 522b8e80941Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 523848b8605Smrg const __DRIextension **extensions; 524848b8605Smrg 525848b8605Smrg extensions = dri2_open_driver(disp); 526848b8605Smrg if (!extensions) 527848b8605Smrg return EGL_FALSE; 528848b8605Smrg 529b8e80941Smrg if (!dri2_bind_extensions(dri2_dpy, driver_extensions, extensions, false)) { 530848b8605Smrg dlclose(dri2_dpy->driver); 531848b8605Smrg return EGL_FALSE; 532848b8605Smrg } 533848b8605Smrg dri2_dpy->driver_extensions = extensions; 534848b8605Smrg 535b8e80941Smrg dri2_bind_extensions(dri2_dpy, optional_driver_extensions, extensions, true); 536b8e80941Smrg 537848b8605Smrg return EGL_TRUE; 538848b8605Smrg} 539848b8605Smrg 540b8e80941SmrgEGLBoolean 541b8e80941Smrgdri2_load_driver(_EGLDisplay *disp) 542b8e80941Smrg{ 543b8e80941Smrg return dri2_load_driver_common(disp, dri2_driver_extensions); 544b8e80941Smrg} 545b8e80941Smrg 546b8e80941SmrgEGLBoolean 547b8e80941Smrgdri2_load_driver_dri3(_EGLDisplay *disp) 548b8e80941Smrg{ 549b8e80941Smrg return dri2_load_driver_common(disp, dri3_driver_extensions); 550b8e80941Smrg} 551b8e80941Smrg 552848b8605SmrgEGLBoolean 553848b8605Smrgdri2_load_driver_swrast(_EGLDisplay *disp) 554848b8605Smrg{ 555b8e80941Smrg return dri2_load_driver_common(disp, swrast_driver_extensions); 556b8e80941Smrg} 557848b8605Smrg 558b8e80941Smrgstatic unsigned 559b8e80941Smrgdri2_renderer_query_integer(struct dri2_egl_display *dri2_dpy, int param) 560b8e80941Smrg{ 561b8e80941Smrg const __DRI2rendererQueryExtension *rendererQuery = dri2_dpy->rendererQuery; 562b8e80941Smrg unsigned int value = 0; 563848b8605Smrg 564b8e80941Smrg if (!rendererQuery || 565b8e80941Smrg rendererQuery->queryInteger(dri2_dpy->dri_screen, param, &value) == -1) 566b8e80941Smrg return 0; 567848b8605Smrg 568b8e80941Smrg return value; 569b8e80941Smrg} 570b8e80941Smrg 571b8e80941Smrgstatic const char * 572b8e80941Smrgdri2_query_driver_name(_EGLDisplay *disp) 573b8e80941Smrg{ 574b8e80941Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 575b8e80941Smrg return dri2_dpy->driver_name; 576b8e80941Smrg} 577b8e80941Smrg 578b8e80941Smrgstatic char * 579b8e80941Smrgdri2_query_driver_config(_EGLDisplay *disp) 580b8e80941Smrg{ 581b8e80941Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 582b8e80941Smrg const __DRIconfigOptionsExtension *ext = dri2_dpy->configOptions; 583b8e80941Smrg 584b8e80941Smrg if (ext->base.version >= 2) 585b8e80941Smrg return ext->getXml(dri2_dpy->driver_name); 586b8e80941Smrg 587b8e80941Smrg return strdup(ext->xml); 588848b8605Smrg} 589848b8605Smrg 590b8e80941Smrg 591848b8605Smrgvoid 592848b8605Smrgdri2_setup_screen(_EGLDisplay *disp) 593848b8605Smrg{ 594848b8605Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 595848b8605Smrg unsigned int api_mask; 596848b8605Smrg 597b8e80941Smrg /* 598b8e80941Smrg * EGL 1.5 specification defines the default value to 1. Moreover, 599b8e80941Smrg * eglSwapInterval() is required to clamp requested value to the supported 600b8e80941Smrg * range. Since the default value is implicitly assumed to be supported, 601b8e80941Smrg * use it as both minimum and maximum for the platforms that do not allow 602b8e80941Smrg * changing the interval. Platforms, which allow it (e.g. x11, wayland) 603b8e80941Smrg * override these values already. 604b8e80941Smrg */ 605b8e80941Smrg dri2_dpy->min_swap_interval = 1; 606b8e80941Smrg dri2_dpy->max_swap_interval = 1; 607b8e80941Smrg dri2_dpy->default_swap_interval = 1; 608b8e80941Smrg 609b8e80941Smrg if (dri2_dpy->image_driver) { 610b8e80941Smrg api_mask = dri2_dpy->image_driver->getAPIMask(dri2_dpy->dri_screen); 611b8e80941Smrg } else if (dri2_dpy->dri2) { 612848b8605Smrg api_mask = dri2_dpy->dri2->getAPIMask(dri2_dpy->dri_screen); 613848b8605Smrg } else { 614848b8605Smrg assert(dri2_dpy->swrast); 615848b8605Smrg api_mask = 1 << __DRI_API_OPENGL | 616848b8605Smrg 1 << __DRI_API_GLES | 617848b8605Smrg 1 << __DRI_API_GLES2 | 618848b8605Smrg 1 << __DRI_API_GLES3; 619848b8605Smrg } 620848b8605Smrg 621848b8605Smrg disp->ClientAPIs = 0; 622b8e80941Smrg if ((api_mask & (1 <<__DRI_API_OPENGL)) && _eglIsApiValid(EGL_OPENGL_API)) 623848b8605Smrg disp->ClientAPIs |= EGL_OPENGL_BIT; 624b8e80941Smrg if ((api_mask & (1 << __DRI_API_GLES)) && _eglIsApiValid(EGL_OPENGL_ES_API)) 625848b8605Smrg disp->ClientAPIs |= EGL_OPENGL_ES_BIT; 626b8e80941Smrg if ((api_mask & (1 << __DRI_API_GLES2)) && _eglIsApiValid(EGL_OPENGL_ES_API)) 627848b8605Smrg disp->ClientAPIs |= EGL_OPENGL_ES2_BIT; 628b8e80941Smrg if ((api_mask & (1 << __DRI_API_GLES3)) && _eglIsApiValid(EGL_OPENGL_ES_API)) 629848b8605Smrg disp->ClientAPIs |= EGL_OPENGL_ES3_BIT_KHR; 630848b8605Smrg 631b8e80941Smrg assert(dri2_dpy->image_driver || dri2_dpy->dri2 || dri2_dpy->swrast); 632b8e80941Smrg disp->Extensions.KHR_no_config_context = EGL_TRUE; 633848b8605Smrg disp->Extensions.KHR_surfaceless_context = EGL_TRUE; 634848b8605Smrg 635b8e80941Smrg if (dri2_dpy->configOptions) { 636b8e80941Smrg disp->Extensions.MESA_query_driver = EGL_TRUE; 637b8e80941Smrg } 638b8e80941Smrg 639b8e80941Smrg /* Report back to EGL the bitmask of priorities supported */ 640b8e80941Smrg disp->Extensions.IMG_context_priority = 641b8e80941Smrg dri2_renderer_query_integer(dri2_dpy, 642b8e80941Smrg __DRI2_RENDERER_HAS_CONTEXT_PRIORITY); 643b8e80941Smrg 644b8e80941Smrg disp->Extensions.EXT_pixel_format_float = EGL_TRUE; 645b8e80941Smrg 646b8e80941Smrg if (dri2_renderer_query_integer(dri2_dpy, 647b8e80941Smrg __DRI2_RENDERER_HAS_FRAMEBUFFER_SRGB)) 648b8e80941Smrg disp->Extensions.KHR_gl_colorspace = EGL_TRUE; 649b8e80941Smrg 650b8e80941Smrg if (dri2_dpy->image_driver || 651b8e80941Smrg (dri2_dpy->dri2 && dri2_dpy->dri2->base.version >= 3) || 652b8e80941Smrg (dri2_dpy->swrast && dri2_dpy->swrast->base.version >= 3)) { 653848b8605Smrg disp->Extensions.KHR_create_context = EGL_TRUE; 654848b8605Smrg 655848b8605Smrg if (dri2_dpy->robustness) 656848b8605Smrg disp->Extensions.EXT_create_context_robustness = EGL_TRUE; 657848b8605Smrg } 658848b8605Smrg 659b8e80941Smrg if (dri2_dpy->no_error) 660b8e80941Smrg disp->Extensions.KHR_create_context_no_error = EGL_TRUE; 661b8e80941Smrg 662b8e80941Smrg if (dri2_dpy->fence) { 663b8e80941Smrg disp->Extensions.KHR_fence_sync = EGL_TRUE; 664b8e80941Smrg disp->Extensions.KHR_wait_sync = EGL_TRUE; 665b8e80941Smrg if (dri2_dpy->fence->get_fence_from_cl_event) 666b8e80941Smrg disp->Extensions.KHR_cl_event2 = EGL_TRUE; 667b8e80941Smrg if (dri2_dpy->fence->base.version >= 2 && 668b8e80941Smrg dri2_dpy->fence->get_capabilities) { 669b8e80941Smrg unsigned capabilities = 670b8e80941Smrg dri2_dpy->fence->get_capabilities(dri2_dpy->dri_screen); 671b8e80941Smrg disp->Extensions.ANDROID_native_fence_sync = 672b8e80941Smrg (capabilities & __DRI_FENCE_CAP_NATIVE_FD) != 0; 673b8e80941Smrg } 674b8e80941Smrg } 675b8e80941Smrg 676b8e80941Smrg if (dri2_dpy->blob) 677b8e80941Smrg disp->Extensions.ANDROID_blob_cache = EGL_TRUE; 678b8e80941Smrg 679b8e80941Smrg disp->Extensions.KHR_reusable_sync = EGL_TRUE; 680b8e80941Smrg 681848b8605Smrg if (dri2_dpy->image) { 682848b8605Smrg if (dri2_dpy->image->base.version >= 10 && 683848b8605Smrg dri2_dpy->image->getCapabilities != NULL) { 684848b8605Smrg int capabilities; 685848b8605Smrg 686848b8605Smrg capabilities = dri2_dpy->image->getCapabilities(dri2_dpy->dri_screen); 687848b8605Smrg disp->Extensions.MESA_drm_image = (capabilities & __DRI_IMAGE_CAP_GLOBAL_NAMES) != 0; 688b8e80941Smrg 689b8e80941Smrg if (dri2_dpy->image->base.version >= 11) 690b8e80941Smrg disp->Extensions.MESA_image_dma_buf_export = EGL_TRUE; 691b8e80941Smrg } else { 692848b8605Smrg disp->Extensions.MESA_drm_image = EGL_TRUE; 693b8e80941Smrg if (dri2_dpy->image->base.version >= 11) 694b8e80941Smrg disp->Extensions.MESA_image_dma_buf_export = EGL_TRUE; 695b8e80941Smrg } 696848b8605Smrg 697848b8605Smrg disp->Extensions.KHR_image_base = EGL_TRUE; 698848b8605Smrg disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE; 699848b8605Smrg if (dri2_dpy->image->base.version >= 5 && 700848b8605Smrg dri2_dpy->image->createImageFromTexture) { 701848b8605Smrg disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE; 702848b8605Smrg disp->Extensions.KHR_gl_texture_cubemap_image = EGL_TRUE; 703b8e80941Smrg 704b8e80941Smrg if (dri2_renderer_query_integer(dri2_dpy, 705b8e80941Smrg __DRI2_RENDERER_HAS_TEXTURE_3D)) 706b8e80941Smrg disp->Extensions.KHR_gl_texture_3D_image = EGL_TRUE; 707848b8605Smrg } 708b8e80941Smrg#ifdef HAVE_LIBDRM 709848b8605Smrg if (dri2_dpy->image->base.version >= 8 && 710848b8605Smrg dri2_dpy->image->createImageFromDmaBufs) { 711848b8605Smrg disp->Extensions.EXT_image_dma_buf_import = EGL_TRUE; 712848b8605Smrg } 713b8e80941Smrg if (dri2_dpy->image->base.version >= 15 && 714b8e80941Smrg dri2_dpy->image->createImageFromDmaBufs2 && 715b8e80941Smrg dri2_dpy->image->queryDmaBufFormats && 716b8e80941Smrg dri2_dpy->image->queryDmaBufModifiers) { 717b8e80941Smrg disp->Extensions.EXT_image_dma_buf_import_modifiers = EGL_TRUE; 718b8e80941Smrg } 719848b8605Smrg#endif 720848b8605Smrg } 721b8e80941Smrg 722b8e80941Smrg if (dri2_dpy->flush_control) 723b8e80941Smrg disp->Extensions.KHR_context_flush_control = EGL_TRUE; 724b8e80941Smrg} 725b8e80941Smrg 726b8e80941Smrgvoid 727b8e80941Smrgdri2_setup_swap_interval(_EGLDisplay *disp, int max_swap_interval) 728b8e80941Smrg{ 729b8e80941Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 730b8e80941Smrg GLint vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1; 731b8e80941Smrg 732b8e80941Smrg /* Allow driconf to override applications.*/ 733b8e80941Smrg if (dri2_dpy->config) 734b8e80941Smrg dri2_dpy->config->configQueryi(dri2_dpy->dri_screen, 735b8e80941Smrg "vblank_mode", &vblank_mode); 736b8e80941Smrg switch (vblank_mode) { 737b8e80941Smrg case DRI_CONF_VBLANK_NEVER: 738b8e80941Smrg dri2_dpy->min_swap_interval = 0; 739b8e80941Smrg dri2_dpy->max_swap_interval = 0; 740b8e80941Smrg dri2_dpy->default_swap_interval = 0; 741b8e80941Smrg break; 742b8e80941Smrg case DRI_CONF_VBLANK_ALWAYS_SYNC: 743b8e80941Smrg dri2_dpy->min_swap_interval = 1; 744b8e80941Smrg dri2_dpy->max_swap_interval = max_swap_interval; 745b8e80941Smrg dri2_dpy->default_swap_interval = 1; 746b8e80941Smrg break; 747b8e80941Smrg case DRI_CONF_VBLANK_DEF_INTERVAL_0: 748b8e80941Smrg dri2_dpy->min_swap_interval = 0; 749b8e80941Smrg dri2_dpy->max_swap_interval = max_swap_interval; 750b8e80941Smrg dri2_dpy->default_swap_interval = 0; 751b8e80941Smrg break; 752b8e80941Smrg default: 753b8e80941Smrg case DRI_CONF_VBLANK_DEF_INTERVAL_1: 754b8e80941Smrg dri2_dpy->min_swap_interval = 0; 755b8e80941Smrg dri2_dpy->max_swap_interval = max_swap_interval; 756b8e80941Smrg dri2_dpy->default_swap_interval = 1; 757b8e80941Smrg break; 758b8e80941Smrg } 759848b8605Smrg} 760848b8605Smrg 761b8e80941Smrg/* All platforms but DRM call this function to create the screen and populate 762b8e80941Smrg * the driver_configs. DRM inherits that information from its display - GBM. 763b8e80941Smrg */ 764848b8605SmrgEGLBoolean 765848b8605Smrgdri2_create_screen(_EGLDisplay *disp) 766848b8605Smrg{ 767b8e80941Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 768848b8605Smrg 769b8e80941Smrg if (dri2_dpy->image_driver) { 770b8e80941Smrg dri2_dpy->dri_screen = 771b8e80941Smrg dri2_dpy->image_driver->createNewScreen2(0, dri2_dpy->fd, 772b8e80941Smrg dri2_dpy->loader_extensions, 773b8e80941Smrg dri2_dpy->driver_extensions, 774b8e80941Smrg &dri2_dpy->driver_configs, 775b8e80941Smrg disp); 776b8e80941Smrg } else if (dri2_dpy->dri2) { 777848b8605Smrg if (dri2_dpy->dri2->base.version >= 4) { 778848b8605Smrg dri2_dpy->dri_screen = 779848b8605Smrg dri2_dpy->dri2->createNewScreen2(0, dri2_dpy->fd, 780b8e80941Smrg dri2_dpy->loader_extensions, 781848b8605Smrg dri2_dpy->driver_extensions, 782848b8605Smrg &dri2_dpy->driver_configs, disp); 783848b8605Smrg } else { 784848b8605Smrg dri2_dpy->dri_screen = 785848b8605Smrg dri2_dpy->dri2->createNewScreen(0, dri2_dpy->fd, 786b8e80941Smrg dri2_dpy->loader_extensions, 787848b8605Smrg &dri2_dpy->driver_configs, disp); 788848b8605Smrg } 789848b8605Smrg } else { 790848b8605Smrg assert(dri2_dpy->swrast); 791848b8605Smrg if (dri2_dpy->swrast->base.version >= 4) { 792848b8605Smrg dri2_dpy->dri_screen = 793b8e80941Smrg dri2_dpy->swrast->createNewScreen2(0, dri2_dpy->loader_extensions, 794848b8605Smrg dri2_dpy->driver_extensions, 795848b8605Smrg &dri2_dpy->driver_configs, disp); 796848b8605Smrg } else { 797848b8605Smrg dri2_dpy->dri_screen = 798b8e80941Smrg dri2_dpy->swrast->createNewScreen(0, dri2_dpy->loader_extensions, 799848b8605Smrg &dri2_dpy->driver_configs, disp); 800848b8605Smrg } 801848b8605Smrg } 802848b8605Smrg 803848b8605Smrg if (dri2_dpy->dri_screen == NULL) { 804848b8605Smrg _eglLog(_EGL_WARNING, "DRI2: failed to create dri screen"); 805848b8605Smrg return EGL_FALSE; 806848b8605Smrg } 807848b8605Smrg 808b8e80941Smrg dri2_dpy->own_dri_screen = true; 809b8e80941Smrg return EGL_TRUE; 810b8e80941Smrg} 811b8e80941Smrg 812b8e80941SmrgEGLBoolean 813b8e80941Smrgdri2_setup_extensions(_EGLDisplay *disp) 814b8e80941Smrg{ 815b8e80941Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 816b8e80941Smrg const struct dri2_extension_match *mandatory_core_extensions; 817b8e80941Smrg const __DRIextension **extensions; 818848b8605Smrg 819848b8605Smrg extensions = dri2_dpy->core->getExtensions(dri2_dpy->dri_screen); 820848b8605Smrg 821b8e80941Smrg if (dri2_dpy->image_driver || dri2_dpy->dri2) 822b8e80941Smrg mandatory_core_extensions = dri2_core_extensions; 823b8e80941Smrg else 824b8e80941Smrg mandatory_core_extensions = swrast_core_extensions; 825848b8605Smrg 826b8e80941Smrg if (!dri2_bind_extensions(dri2_dpy, mandatory_core_extensions, extensions, false)) 827b8e80941Smrg return EGL_FALSE; 828848b8605Smrg 829b8e80941Smrg#ifdef HAVE_DRI3_MODIFIERS 830b8e80941Smrg dri2_dpy->multibuffers_available = 831b8e80941Smrg (dri2_dpy->dri3_major_version > 1 || (dri2_dpy->dri3_major_version == 1 && 832b8e80941Smrg dri2_dpy->dri3_minor_version >= 2)) && 833b8e80941Smrg (dri2_dpy->present_major_version > 1 || (dri2_dpy->present_major_version == 1 && 834b8e80941Smrg dri2_dpy->present_minor_version >= 2)) && 835b8e80941Smrg (dri2_dpy->image && dri2_dpy->image->base.version >= 15); 836b8e80941Smrg#endif 837848b8605Smrg 838b8e80941Smrg dri2_bind_extensions(dri2_dpy, optional_core_extensions, extensions, true); 839b8e80941Smrg return EGL_TRUE; 840848b8605Smrg} 841848b8605Smrg 842848b8605Smrg/** 843848b8605Smrg * Called via eglInitialize(), GLX_drv->API.Initialize(). 844b8e80941Smrg * 845b8e80941Smrg * This must be guaranteed to be called exactly once, even if eglInitialize is 846b8e80941Smrg * called many times (without a eglTerminate in between). 847848b8605Smrg */ 848848b8605Smrgstatic EGLBoolean 849848b8605Smrgdri2_initialize(_EGLDriver *drv, _EGLDisplay *disp) 850848b8605Smrg{ 851b8e80941Smrg EGLBoolean ret = EGL_FALSE; 852b8e80941Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 853b8e80941Smrg 854b8e80941Smrg /* In the case where the application calls eglMakeCurrent(context1), 855b8e80941Smrg * eglTerminate, then eglInitialize again (without a call to eglReleaseThread 856b8e80941Smrg * or eglMakeCurrent(NULL) before that), dri2_dpy structure is still 857b8e80941Smrg * initialized, as we need it to be able to free context1 correctly. 858b8e80941Smrg * 859b8e80941Smrg * It would probably be safest to forcibly release the display with 860b8e80941Smrg * dri2_display_release, to make sure the display is reinitialized correctly. 861b8e80941Smrg * However, the EGL spec states that we need to keep a reference to the 862b8e80941Smrg * current context (so we cannot call dri2_make_current(NULL)), and therefore 863b8e80941Smrg * we would leak context1 as we would be missing the old display connection 864b8e80941Smrg * to free it up correctly. 865b8e80941Smrg */ 866b8e80941Smrg if (dri2_dpy) { 867b8e80941Smrg dri2_dpy->ref_count++; 868b8e80941Smrg return EGL_TRUE; 869b8e80941Smrg } 870b8e80941Smrg 871b8e80941Smrg loader_set_logger(_eglLog); 872848b8605Smrg 873848b8605Smrg switch (disp->Platform) { 874b8e80941Smrg case _EGL_PLATFORM_SURFACELESS: 875b8e80941Smrg ret = dri2_initialize_surfaceless(drv, disp); 876b8e80941Smrg break; 877848b8605Smrg case _EGL_PLATFORM_X11: 878b8e80941Smrg ret = dri2_initialize_x11(drv, disp); 879b8e80941Smrg break; 880848b8605Smrg case _EGL_PLATFORM_DRM: 881b8e80941Smrg ret = dri2_initialize_drm(drv, disp); 882b8e80941Smrg break; 883848b8605Smrg case _EGL_PLATFORM_WAYLAND: 884b8e80941Smrg ret = dri2_initialize_wayland(drv, disp); 885b8e80941Smrg break; 886848b8605Smrg case _EGL_PLATFORM_ANDROID: 887b8e80941Smrg ret = dri2_initialize_android(drv, disp); 888b8e80941Smrg break; 889848b8605Smrg default: 890b8e80941Smrg unreachable("Callers ensure we cannot get here."); 891848b8605Smrg return EGL_FALSE; 892848b8605Smrg } 893b8e80941Smrg 894b8e80941Smrg if (!ret) 895b8e80941Smrg return EGL_FALSE; 896b8e80941Smrg 897b8e80941Smrg dri2_dpy = dri2_egl_display(disp); 898b8e80941Smrg dri2_dpy->ref_count++; 899b8e80941Smrg 900b8e80941Smrg return EGL_TRUE; 901848b8605Smrg} 902848b8605Smrg 903848b8605Smrg/** 904b8e80941Smrg * Decrement display reference count, and free up display if necessary. 905848b8605Smrg */ 906b8e80941Smrgstatic void 907b8e80941Smrgdri2_display_release(_EGLDisplay *disp) 908848b8605Smrg{ 909b8e80941Smrg struct dri2_egl_display *dri2_dpy; 910b8e80941Smrg 911b8e80941Smrg if (!disp) 912b8e80941Smrg return; 913b8e80941Smrg 914b8e80941Smrg dri2_dpy = dri2_egl_display(disp); 915b8e80941Smrg 916b8e80941Smrg assert(dri2_dpy->ref_count > 0); 917b8e80941Smrg dri2_dpy->ref_count--; 918b8e80941Smrg 919b8e80941Smrg if (dri2_dpy->ref_count > 0) 920b8e80941Smrg return; 921848b8605Smrg 922848b8605Smrg _eglCleanupDisplay(disp); 923b8e80941Smrg dri2_display_destroy(disp); 924b8e80941Smrg} 925b8e80941Smrg 926b8e80941Smrgvoid 927b8e80941Smrgdri2_display_destroy(_EGLDisplay *disp) 928b8e80941Smrg{ 929b8e80941Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 930848b8605Smrg 931b8e80941Smrg if (dri2_dpy->own_dri_screen) { 932b8e80941Smrg if (dri2_dpy->vtbl && dri2_dpy->vtbl->close_screen_notify) 933b8e80941Smrg dri2_dpy->vtbl->close_screen_notify(disp); 934848b8605Smrg dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen); 935b8e80941Smrg } 936b8e80941Smrg if (dri2_dpy->fd >= 0) 937848b8605Smrg close(dri2_dpy->fd); 938848b8605Smrg if (dri2_dpy->driver) 939848b8605Smrg dlclose(dri2_dpy->driver); 940848b8605Smrg free(dri2_dpy->driver_name); 941848b8605Smrg 942b8e80941Smrg#ifdef HAVE_WAYLAND_PLATFORM 943b8e80941Smrg free(dri2_dpy->device_name); 944b8e80941Smrg#endif 945b8e80941Smrg 946848b8605Smrg switch (disp->Platform) { 947848b8605Smrg case _EGL_PLATFORM_X11: 948b8e80941Smrg dri2_teardown_x11(dri2_dpy); 949848b8605Smrg break; 950848b8605Smrg case _EGL_PLATFORM_DRM: 951b8e80941Smrg dri2_teardown_drm(dri2_dpy); 952848b8605Smrg break; 953848b8605Smrg case _EGL_PLATFORM_WAYLAND: 954b8e80941Smrg dri2_teardown_wayland(dri2_dpy); 955848b8605Smrg break; 956848b8605Smrg default: 957b8e80941Smrg /* TODO: add teardown for other platforms */ 958848b8605Smrg break; 959848b8605Smrg } 960848b8605Smrg 961b8e80941Smrg /* The drm platform does not create the screen/driver_configs but reuses 962b8e80941Smrg * the ones from the gbm device. As such the gbm itself is responsible 963b8e80941Smrg * for the cleanup. 964b8e80941Smrg */ 965b8e80941Smrg if (disp->Platform != _EGL_PLATFORM_DRM && dri2_dpy->driver_configs) { 966b8e80941Smrg for (unsigned i = 0; dri2_dpy->driver_configs[i]; i++) 967b8e80941Smrg free((__DRIconfig *) dri2_dpy->driver_configs[i]); 968b8e80941Smrg free(dri2_dpy->driver_configs); 969b8e80941Smrg } 970848b8605Smrg free(dri2_dpy); 971848b8605Smrg disp->DriverData = NULL; 972b8e80941Smrg} 973b8e80941Smrg 974b8e80941Smrg__DRIbuffer * 975b8e80941Smrgdri2_egl_surface_alloc_local_buffer(struct dri2_egl_surface *dri2_surf, 976b8e80941Smrg unsigned int att, unsigned int format) 977b8e80941Smrg{ 978b8e80941Smrg struct dri2_egl_display *dri2_dpy = 979b8e80941Smrg dri2_egl_display(dri2_surf->base.Resource.Display); 980b8e80941Smrg 981b8e80941Smrg if (att >= ARRAY_SIZE(dri2_surf->local_buffers)) 982b8e80941Smrg return NULL; 983b8e80941Smrg 984b8e80941Smrg if (!dri2_surf->local_buffers[att]) { 985b8e80941Smrg dri2_surf->local_buffers[att] = 986b8e80941Smrg dri2_dpy->dri2->allocateBuffer(dri2_dpy->dri_screen, att, format, 987b8e80941Smrg dri2_surf->base.Width, dri2_surf->base.Height); 988b8e80941Smrg } 989b8e80941Smrg 990b8e80941Smrg return dri2_surf->local_buffers[att]; 991b8e80941Smrg} 992b8e80941Smrg 993b8e80941Smrgvoid 994b8e80941Smrgdri2_egl_surface_free_local_buffers(struct dri2_egl_surface *dri2_surf) 995b8e80941Smrg{ 996b8e80941Smrg struct dri2_egl_display *dri2_dpy = 997b8e80941Smrg dri2_egl_display(dri2_surf->base.Resource.Display); 998b8e80941Smrg 999b8e80941Smrg for (int i = 0; i < ARRAY_SIZE(dri2_surf->local_buffers); i++) { 1000b8e80941Smrg if (dri2_surf->local_buffers[i]) { 1001b8e80941Smrg dri2_dpy->dri2->releaseBuffer(dri2_dpy->dri_screen, 1002b8e80941Smrg dri2_surf->local_buffers[i]); 1003b8e80941Smrg dri2_surf->local_buffers[i] = NULL; 1004b8e80941Smrg } 1005b8e80941Smrg } 1006b8e80941Smrg} 1007b8e80941Smrg 1008b8e80941Smrg/** 1009b8e80941Smrg * Called via eglTerminate(), drv->API.Terminate(). 1010b8e80941Smrg * 1011b8e80941Smrg * This must be guaranteed to be called exactly once, even if eglTerminate is 1012b8e80941Smrg * called many times (without a eglInitialize in between). 1013b8e80941Smrg */ 1014b8e80941Smrgstatic EGLBoolean 1015b8e80941Smrgdri2_terminate(_EGLDriver *drv, _EGLDisplay *disp) 1016b8e80941Smrg{ 1017b8e80941Smrg /* Release all non-current Context/Surfaces. */ 1018b8e80941Smrg _eglReleaseDisplayResources(drv, disp); 1019b8e80941Smrg 1020b8e80941Smrg dri2_display_release(disp); 1021848b8605Smrg 1022848b8605Smrg return EGL_TRUE; 1023848b8605Smrg} 1024848b8605Smrg 1025848b8605Smrg/** 1026848b8605Smrg * Set the error code after a call to 1027848b8605Smrg * dri2_egl_display::dri2::createContextAttribs. 1028848b8605Smrg */ 1029848b8605Smrgstatic void 1030848b8605Smrgdri2_create_context_attribs_error(int dri_error) 1031848b8605Smrg{ 1032848b8605Smrg EGLint egl_error; 1033848b8605Smrg 1034848b8605Smrg switch (dri_error) { 1035848b8605Smrg case __DRI_CTX_ERROR_SUCCESS: 1036848b8605Smrg return; 1037848b8605Smrg 1038848b8605Smrg case __DRI_CTX_ERROR_NO_MEMORY: 1039848b8605Smrg egl_error = EGL_BAD_ALLOC; 1040848b8605Smrg break; 1041848b8605Smrg 1042848b8605Smrg /* From the EGL_KHR_create_context spec, section "Errors": 1043848b8605Smrg * 1044848b8605Smrg * * If <config> does not support a client API context compatible 1045848b8605Smrg * with the requested API major and minor version, [...] context flags, 1046848b8605Smrg * and context reset notification behavior (for client API types where 1047848b8605Smrg * these attributes are supported), then an EGL_BAD_MATCH error is 1048848b8605Smrg * generated. 1049848b8605Smrg * 1050848b8605Smrg * * If an OpenGL ES context is requested and the values for 1051848b8605Smrg * attributes EGL_CONTEXT_MAJOR_VERSION_KHR and 1052848b8605Smrg * EGL_CONTEXT_MINOR_VERSION_KHR specify an OpenGL ES version that 1053848b8605Smrg * is not defined, than an EGL_BAD_MATCH error is generated. 1054848b8605Smrg * 1055848b8605Smrg * * If an OpenGL context is requested, the requested version is 1056848b8605Smrg * greater than 3.2, and the value for attribute 1057848b8605Smrg * EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR has no bits set; has any 1058848b8605Smrg * bits set other than EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR and 1059848b8605Smrg * EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; has more than 1060848b8605Smrg * one of these bits set; or if the implementation does not support 1061848b8605Smrg * the requested profile, then an EGL_BAD_MATCH error is generated. 1062848b8605Smrg */ 1063848b8605Smrg case __DRI_CTX_ERROR_BAD_API: 1064848b8605Smrg case __DRI_CTX_ERROR_BAD_VERSION: 1065848b8605Smrg case __DRI_CTX_ERROR_BAD_FLAG: 1066848b8605Smrg egl_error = EGL_BAD_MATCH; 1067848b8605Smrg break; 1068848b8605Smrg 1069848b8605Smrg /* From the EGL_KHR_create_context spec, section "Errors": 1070848b8605Smrg * 1071848b8605Smrg * * If an attribute name or attribute value in <attrib_list> is not 1072848b8605Smrg * recognized (including unrecognized bits in bitmask attributes), 1073848b8605Smrg * then an EGL_BAD_ATTRIBUTE error is generated." 1074848b8605Smrg */ 1075848b8605Smrg case __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE: 1076848b8605Smrg case __DRI_CTX_ERROR_UNKNOWN_FLAG: 1077848b8605Smrg egl_error = EGL_BAD_ATTRIBUTE; 1078848b8605Smrg break; 1079848b8605Smrg 1080848b8605Smrg default: 1081b8e80941Smrg assert(!"unknown dri_error code"); 1082848b8605Smrg egl_error = EGL_BAD_MATCH; 1083848b8605Smrg break; 1084848b8605Smrg } 1085848b8605Smrg 1086848b8605Smrg _eglError(egl_error, "dri2_create_context"); 1087848b8605Smrg} 1088848b8605Smrg 1089b8e80941Smrgstatic bool 1090b8e80941Smrgdri2_fill_context_attribs(struct dri2_egl_context *dri2_ctx, 1091b8e80941Smrg struct dri2_egl_display *dri2_dpy, 1092b8e80941Smrg uint32_t *ctx_attribs, 1093b8e80941Smrg unsigned *num_attribs) 1094b8e80941Smrg{ 1095b8e80941Smrg int pos = 0; 1096b8e80941Smrg 1097b8e80941Smrg assert(*num_attribs >= NUM_ATTRIBS); 1098b8e80941Smrg 1099b8e80941Smrg ctx_attribs[pos++] = __DRI_CTX_ATTRIB_MAJOR_VERSION; 1100b8e80941Smrg ctx_attribs[pos++] = dri2_ctx->base.ClientMajorVersion; 1101b8e80941Smrg ctx_attribs[pos++] = __DRI_CTX_ATTRIB_MINOR_VERSION; 1102b8e80941Smrg ctx_attribs[pos++] = dri2_ctx->base.ClientMinorVersion; 1103b8e80941Smrg 1104b8e80941Smrg if (dri2_ctx->base.Flags != 0 || dri2_ctx->base.NoError) { 1105b8e80941Smrg /* If the implementation doesn't support the __DRI2_ROBUSTNESS 1106b8e80941Smrg * extension, don't even try to send it the robust-access flag. 1107b8e80941Smrg * It may explode. Instead, generate the required EGL error here. 1108b8e80941Smrg */ 1109b8e80941Smrg if ((dri2_ctx->base.Flags & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR) != 0 1110b8e80941Smrg && !dri2_dpy->robustness) { 1111b8e80941Smrg _eglError(EGL_BAD_MATCH, "eglCreateContext"); 1112b8e80941Smrg return false; 1113b8e80941Smrg } 1114b8e80941Smrg 1115b8e80941Smrg ctx_attribs[pos++] = __DRI_CTX_ATTRIB_FLAGS; 1116b8e80941Smrg ctx_attribs[pos++] = dri2_ctx->base.Flags | 1117b8e80941Smrg (dri2_ctx->base.NoError ? __DRI_CTX_FLAG_NO_ERROR : 0); 1118b8e80941Smrg } 1119b8e80941Smrg 1120b8e80941Smrg if (dri2_ctx->base.ResetNotificationStrategy != EGL_NO_RESET_NOTIFICATION_KHR) { 1121b8e80941Smrg /* If the implementation doesn't support the __DRI2_ROBUSTNESS 1122b8e80941Smrg * extension, don't even try to send it a reset strategy. It may 1123b8e80941Smrg * explode. Instead, generate the required EGL error here. 1124b8e80941Smrg */ 1125b8e80941Smrg if (!dri2_dpy->robustness) { 1126b8e80941Smrg _eglError(EGL_BAD_CONFIG, "eglCreateContext"); 1127b8e80941Smrg return false; 1128b8e80941Smrg } 1129b8e80941Smrg 1130b8e80941Smrg ctx_attribs[pos++] = __DRI_CTX_ATTRIB_RESET_STRATEGY; 1131b8e80941Smrg ctx_attribs[pos++] = __DRI_CTX_RESET_LOSE_CONTEXT; 1132b8e80941Smrg } 1133b8e80941Smrg 1134b8e80941Smrg if (dri2_ctx->base.ContextPriority != EGL_CONTEXT_PRIORITY_MEDIUM_IMG) { 1135b8e80941Smrg unsigned val; 1136b8e80941Smrg 1137b8e80941Smrg switch (dri2_ctx->base.ContextPriority) { 1138b8e80941Smrg case EGL_CONTEXT_PRIORITY_HIGH_IMG: 1139b8e80941Smrg val = __DRI_CTX_PRIORITY_HIGH; 1140b8e80941Smrg break; 1141b8e80941Smrg case EGL_CONTEXT_PRIORITY_MEDIUM_IMG: 1142b8e80941Smrg val = __DRI_CTX_PRIORITY_MEDIUM; 1143b8e80941Smrg break; 1144b8e80941Smrg case EGL_CONTEXT_PRIORITY_LOW_IMG: 1145b8e80941Smrg val = __DRI_CTX_PRIORITY_LOW; 1146b8e80941Smrg break; 1147b8e80941Smrg default: 1148b8e80941Smrg _eglError(EGL_BAD_CONFIG, "eglCreateContext"); 1149b8e80941Smrg return false; 1150b8e80941Smrg } 1151b8e80941Smrg 1152b8e80941Smrg ctx_attribs[pos++] = __DRI_CTX_ATTRIB_PRIORITY; 1153b8e80941Smrg ctx_attribs[pos++] = val; 1154b8e80941Smrg } 1155b8e80941Smrg 1156b8e80941Smrg if (dri2_ctx->base.ReleaseBehavior == EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR) { 1157b8e80941Smrg ctx_attribs[pos++] = __DRI_CTX_ATTRIB_RELEASE_BEHAVIOR; 1158b8e80941Smrg ctx_attribs[pos++] = __DRI_CTX_RELEASE_BEHAVIOR_NONE; 1159b8e80941Smrg } 1160b8e80941Smrg 1161b8e80941Smrg *num_attribs = pos; 1162b8e80941Smrg 1163b8e80941Smrg return true; 1164b8e80941Smrg} 1165b8e80941Smrg 1166848b8605Smrg/** 1167848b8605Smrg * Called via eglCreateContext(), drv->API.CreateContext(). 1168848b8605Smrg */ 1169848b8605Smrgstatic _EGLContext * 1170848b8605Smrgdri2_create_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf, 1171b8e80941Smrg _EGLContext *share_list, const EGLint *attrib_list) 1172848b8605Smrg{ 1173848b8605Smrg struct dri2_egl_context *dri2_ctx; 1174848b8605Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1175848b8605Smrg struct dri2_egl_context *dri2_ctx_shared = dri2_egl_context(share_list); 1176848b8605Smrg __DRIcontext *shared = 1177848b8605Smrg dri2_ctx_shared ? dri2_ctx_shared->dri_context : NULL; 1178848b8605Smrg struct dri2_egl_config *dri2_config = dri2_egl_config(conf); 1179848b8605Smrg const __DRIconfig *dri_config; 1180848b8605Smrg int api; 1181b8e80941Smrg unsigned error; 1182b8e80941Smrg unsigned num_attribs = NUM_ATTRIBS; 1183b8e80941Smrg uint32_t ctx_attribs[NUM_ATTRIBS]; 1184848b8605Smrg 1185848b8605Smrg (void) drv; 1186848b8605Smrg 1187848b8605Smrg dri2_ctx = malloc(sizeof *dri2_ctx); 1188848b8605Smrg if (!dri2_ctx) { 1189848b8605Smrg _eglError(EGL_BAD_ALLOC, "eglCreateContext"); 1190848b8605Smrg return NULL; 1191848b8605Smrg } 1192848b8605Smrg 1193848b8605Smrg if (!_eglInitContext(&dri2_ctx->base, disp, conf, attrib_list)) 1194848b8605Smrg goto cleanup; 1195848b8605Smrg 1196b8e80941Smrg /* The EGL_EXT_create_context_robustness spec says: 1197b8e80941Smrg * 1198b8e80941Smrg * "Add to the eglCreateContext context creation errors: [...] 1199b8e80941Smrg * 1200b8e80941Smrg * * If the reset notification behavior of <share_context> and the 1201b8e80941Smrg * newly created context are different then an EGL_BAD_MATCH error is 1202b8e80941Smrg * generated." 1203b8e80941Smrg */ 1204b8e80941Smrg if (share_list && share_list->ResetNotificationStrategy != 1205b8e80941Smrg dri2_ctx->base.ResetNotificationStrategy) { 1206b8e80941Smrg _eglError(EGL_BAD_MATCH, "eglCreateContext"); 1207b8e80941Smrg goto cleanup; 1208b8e80941Smrg } 1209b8e80941Smrg 1210b8e80941Smrg /* The EGL_KHR_create_context_no_error spec says: 1211b8e80941Smrg * 1212b8e80941Smrg * "BAD_MATCH is generated if the value of EGL_CONTEXT_OPENGL_NO_ERROR_KHR 1213b8e80941Smrg * used to create <share_context> does not match the value of 1214b8e80941Smrg * EGL_CONTEXT_OPENGL_NO_ERROR_KHR for the context being created." 1215b8e80941Smrg */ 1216b8e80941Smrg if (share_list && share_list->NoError != dri2_ctx->base.NoError) { 1217b8e80941Smrg _eglError(EGL_BAD_MATCH, "eglCreateContext"); 1218b8e80941Smrg goto cleanup; 1219b8e80941Smrg } 1220b8e80941Smrg 1221848b8605Smrg switch (dri2_ctx->base.ClientAPI) { 1222848b8605Smrg case EGL_OPENGL_ES_API: 1223848b8605Smrg switch (dri2_ctx->base.ClientMajorVersion) { 1224848b8605Smrg case 1: 1225848b8605Smrg api = __DRI_API_GLES; 1226848b8605Smrg break; 1227848b8605Smrg case 2: 1228848b8605Smrg api = __DRI_API_GLES2; 1229848b8605Smrg break; 1230848b8605Smrg case 3: 1231848b8605Smrg api = __DRI_API_GLES3; 1232848b8605Smrg break; 1233848b8605Smrg default: 1234848b8605Smrg _eglError(EGL_BAD_PARAMETER, "eglCreateContext"); 1235848b8605Smrg free(dri2_ctx); 1236848b8605Smrg return NULL; 1237848b8605Smrg } 1238848b8605Smrg break; 1239848b8605Smrg case EGL_OPENGL_API: 1240848b8605Smrg if ((dri2_ctx->base.ClientMajorVersion >= 4 1241848b8605Smrg || (dri2_ctx->base.ClientMajorVersion == 3 1242848b8605Smrg && dri2_ctx->base.ClientMinorVersion >= 2)) 1243848b8605Smrg && dri2_ctx->base.Profile == EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR) 1244848b8605Smrg api = __DRI_API_OPENGL_CORE; 1245848b8605Smrg else 1246848b8605Smrg api = __DRI_API_OPENGL; 1247848b8605Smrg break; 1248848b8605Smrg default: 1249848b8605Smrg _eglError(EGL_BAD_PARAMETER, "eglCreateContext"); 1250848b8605Smrg free(dri2_ctx); 1251848b8605Smrg return NULL; 1252848b8605Smrg } 1253848b8605Smrg 1254848b8605Smrg if (conf != NULL) { 1255848b8605Smrg /* The config chosen here isn't necessarily 1256848b8605Smrg * used for surfaces later. 1257848b8605Smrg * A pixmap surface will use the single config. 1258848b8605Smrg * This opportunity depends on disabling the 1259848b8605Smrg * doubleBufferMode check in 1260848b8605Smrg * src/mesa/main/context.c:check_compatible() 1261848b8605Smrg */ 1262b8e80941Smrg if (dri2_config->dri_config[1][0]) 1263b8e80941Smrg dri_config = dri2_config->dri_config[1][0]; 1264848b8605Smrg else 1265b8e80941Smrg dri_config = dri2_config->dri_config[0][0]; 1266848b8605Smrg } 1267848b8605Smrg else 1268848b8605Smrg dri_config = NULL; 1269848b8605Smrg 1270b8e80941Smrg if (!dri2_fill_context_attribs(dri2_ctx, dri2_dpy, ctx_attribs, 1271b8e80941Smrg &num_attribs)) 1272b8e80941Smrg goto cleanup; 1273848b8605Smrg 1274b8e80941Smrg if (dri2_dpy->image_driver) { 1275b8e80941Smrg dri2_ctx->dri_context = 1276b8e80941Smrg dri2_dpy->image_driver->createContextAttribs(dri2_dpy->dri_screen, 1277b8e80941Smrg api, 1278b8e80941Smrg dri_config, 1279b8e80941Smrg shared, 1280b8e80941Smrg num_attribs / 2, 1281b8e80941Smrg ctx_attribs, 1282b8e80941Smrg & error, 1283b8e80941Smrg dri2_ctx); 1284b8e80941Smrg dri2_create_context_attribs_error(error); 1285b8e80941Smrg } else if (dri2_dpy->dri2) { 1286b8e80941Smrg if (dri2_dpy->dri2->base.version >= 3) { 1287b8e80941Smrg dri2_ctx->dri_context = 1288b8e80941Smrg dri2_dpy->dri2->createContextAttribs(dri2_dpy->dri_screen, 1289848b8605Smrg api, 1290848b8605Smrg dri_config, 1291848b8605Smrg shared, 1292848b8605Smrg num_attribs / 2, 1293848b8605Smrg ctx_attribs, 1294848b8605Smrg & error, 1295848b8605Smrg dri2_ctx); 1296b8e80941Smrg dri2_create_context_attribs_error(error); 1297848b8605Smrg } else { 1298b8e80941Smrg dri2_ctx->dri_context = 1299b8e80941Smrg dri2_dpy->dri2->createNewContextForAPI(dri2_dpy->dri_screen, 1300b8e80941Smrg api, 1301b8e80941Smrg dri_config, 1302848b8605Smrg shared, 1303b8e80941Smrg dri2_ctx); 1304848b8605Smrg } 1305848b8605Smrg } else { 1306848b8605Smrg assert(dri2_dpy->swrast); 1307b8e80941Smrg if (dri2_dpy->swrast->base.version >= 3) { 1308b8e80941Smrg dri2_ctx->dri_context = 1309b8e80941Smrg dri2_dpy->swrast->createContextAttribs(dri2_dpy->dri_screen, 1310b8e80941Smrg api, 1311b8e80941Smrg dri_config, 1312b8e80941Smrg shared, 1313b8e80941Smrg num_attribs / 2, 1314b8e80941Smrg ctx_attribs, 1315b8e80941Smrg & error, 1316b8e80941Smrg dri2_ctx); 1317b8e80941Smrg dri2_create_context_attribs_error(error); 1318b8e80941Smrg } else { 1319b8e80941Smrg dri2_ctx->dri_context = 1320b8e80941Smrg dri2_dpy->swrast->createNewContextForAPI(dri2_dpy->dri_screen, 1321b8e80941Smrg api, 1322b8e80941Smrg dri_config, 1323b8e80941Smrg shared, 1324b8e80941Smrg dri2_ctx); 1325b8e80941Smrg } 1326848b8605Smrg } 1327848b8605Smrg 1328848b8605Smrg if (!dri2_ctx->dri_context) 1329848b8605Smrg goto cleanup; 1330848b8605Smrg 1331848b8605Smrg return &dri2_ctx->base; 1332848b8605Smrg 1333848b8605Smrg cleanup: 1334848b8605Smrg free(dri2_ctx); 1335848b8605Smrg return NULL; 1336848b8605Smrg} 1337848b8605Smrg 1338848b8605Smrg/** 1339848b8605Smrg * Called via eglDestroyContext(), drv->API.DestroyContext(). 1340848b8605Smrg */ 1341848b8605Smrgstatic EGLBoolean 1342848b8605Smrgdri2_destroy_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx) 1343848b8605Smrg{ 1344848b8605Smrg struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); 1345848b8605Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1346848b8605Smrg 1347848b8605Smrg if (_eglPutContext(ctx)) { 1348848b8605Smrg dri2_dpy->core->destroyContext(dri2_ctx->dri_context); 1349848b8605Smrg free(dri2_ctx); 1350848b8605Smrg } 1351848b8605Smrg 1352848b8605Smrg return EGL_TRUE; 1353848b8605Smrg} 1354848b8605Smrg 1355b8e80941SmrgEGLBoolean 1356b8e80941Smrgdri2_init_surface(_EGLSurface *surf, _EGLDisplay *disp, EGLint type, 1357b8e80941Smrg _EGLConfig *conf, const EGLint *attrib_list, EGLBoolean enable_out_fence) 1358b8e80941Smrg{ 1359b8e80941Smrg struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); 1360b8e80941Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1361b8e80941Smrg 1362b8e80941Smrg dri2_surf->out_fence_fd = -1; 1363b8e80941Smrg dri2_surf->enable_out_fence = false; 1364b8e80941Smrg if (dri2_dpy->fence && dri2_dpy->fence->base.version >= 2 && 1365b8e80941Smrg dri2_dpy->fence->get_capabilities && 1366b8e80941Smrg (dri2_dpy->fence->get_capabilities(dri2_dpy->dri_screen) & 1367b8e80941Smrg __DRI_FENCE_CAP_NATIVE_FD)) { 1368b8e80941Smrg dri2_surf->enable_out_fence = enable_out_fence; 1369b8e80941Smrg } 1370b8e80941Smrg 1371b8e80941Smrg return _eglInitSurface(surf, disp, type, conf, attrib_list); 1372b8e80941Smrg} 1373b8e80941Smrg 1374b8e80941Smrgstatic void 1375b8e80941Smrgdri2_surface_set_out_fence_fd( _EGLSurface *surf, int fence_fd) 1376b8e80941Smrg{ 1377b8e80941Smrg struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); 1378b8e80941Smrg 1379b8e80941Smrg if (dri2_surf->out_fence_fd >= 0) 1380b8e80941Smrg close(dri2_surf->out_fence_fd); 1381b8e80941Smrg 1382b8e80941Smrg dri2_surf->out_fence_fd = fence_fd; 1383b8e80941Smrg} 1384b8e80941Smrg 1385b8e80941Smrgvoid 1386b8e80941Smrgdri2_fini_surface(_EGLSurface *surf) 1387b8e80941Smrg{ 1388b8e80941Smrg struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); 1389b8e80941Smrg 1390b8e80941Smrg dri2_surface_set_out_fence_fd(surf, -1); 1391b8e80941Smrg dri2_surf->enable_out_fence = false; 1392b8e80941Smrg} 1393b8e80941Smrg 1394b8e80941Smrgstatic EGLBoolean 1395b8e80941Smrgdri2_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf) 1396b8e80941Smrg{ 1397b8e80941Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1398b8e80941Smrg 1399b8e80941Smrg if (!_eglPutSurface(surf)) 1400b8e80941Smrg return EGL_TRUE; 1401b8e80941Smrg 1402b8e80941Smrg return dri2_dpy->vtbl->destroy_surface(drv, disp, surf); 1403b8e80941Smrg} 1404b8e80941Smrg 1405b8e80941Smrgstatic void 1406b8e80941Smrgdri2_surf_update_fence_fd(_EGLContext *ctx, 1407b8e80941Smrg _EGLDisplay *disp, _EGLSurface *surf) 1408b8e80941Smrg{ 1409b8e80941Smrg __DRIcontext *dri_ctx = dri2_egl_context(ctx)->dri_context; 1410b8e80941Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1411b8e80941Smrg struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); 1412b8e80941Smrg int fence_fd = -1; 1413b8e80941Smrg void *fence; 1414b8e80941Smrg 1415b8e80941Smrg if (!dri2_surf->enable_out_fence) 1416b8e80941Smrg return; 1417b8e80941Smrg 1418b8e80941Smrg fence = dri2_dpy->fence->create_fence_fd(dri_ctx, -1); 1419b8e80941Smrg if (fence) { 1420b8e80941Smrg fence_fd = dri2_dpy->fence->get_fence_fd(dri2_dpy->dri_screen, 1421b8e80941Smrg fence); 1422b8e80941Smrg dri2_dpy->fence->destroy_fence(dri2_dpy->dri_screen, fence); 1423b8e80941Smrg } 1424b8e80941Smrg dri2_surface_set_out_fence_fd(surf, fence_fd); 1425b8e80941Smrg} 1426b8e80941Smrg 1427b8e80941SmrgEGLBoolean 1428b8e80941Smrgdri2_create_drawable(struct dri2_egl_display *dri2_dpy, 1429b8e80941Smrg const __DRIconfig *config, 1430b8e80941Smrg struct dri2_egl_surface *dri2_surf) 1431b8e80941Smrg{ 1432b8e80941Smrg __DRIcreateNewDrawableFunc createNewDrawable; 1433b8e80941Smrg void *loaderPrivate = dri2_surf; 1434b8e80941Smrg 1435b8e80941Smrg if (dri2_dpy->image_driver) 1436b8e80941Smrg createNewDrawable = dri2_dpy->image_driver->createNewDrawable; 1437b8e80941Smrg else if (dri2_dpy->dri2) 1438b8e80941Smrg createNewDrawable = dri2_dpy->dri2->createNewDrawable; 1439b8e80941Smrg else if (dri2_dpy->swrast) 1440b8e80941Smrg createNewDrawable = dri2_dpy->swrast->createNewDrawable; 1441b8e80941Smrg else 1442b8e80941Smrg return _eglError(EGL_BAD_ALLOC, "no createNewDrawable"); 1443b8e80941Smrg 1444b8e80941Smrg /* As always gbm is a bit special.. */ 1445b8e80941Smrg#ifdef HAVE_DRM_PLATFORM 1446b8e80941Smrg if (dri2_surf->gbm_surf) 1447b8e80941Smrg loaderPrivate = dri2_surf->gbm_surf; 1448b8e80941Smrg#endif 1449b8e80941Smrg 1450b8e80941Smrg dri2_surf->dri_drawable = (*createNewDrawable)(dri2_dpy->dri_screen, 1451b8e80941Smrg config, loaderPrivate); 1452b8e80941Smrg if (dri2_surf->dri_drawable == NULL) 1453b8e80941Smrg return _eglError(EGL_BAD_ALLOC, "createNewDrawable"); 1454b8e80941Smrg 1455b8e80941Smrg return EGL_TRUE; 1456b8e80941Smrg} 1457b8e80941Smrg 1458848b8605Smrg/** 1459848b8605Smrg * Called via eglMakeCurrent(), drv->API.MakeCurrent(). 1460848b8605Smrg */ 1461848b8605Smrgstatic EGLBoolean 1462848b8605Smrgdri2_make_current(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf, 1463b8e80941Smrg _EGLSurface *rsurf, _EGLContext *ctx) 1464848b8605Smrg{ 1465848b8605Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1466848b8605Smrg struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); 1467b8e80941Smrg _EGLDisplay *old_disp = NULL; 1468b8e80941Smrg struct dri2_egl_display *old_dri2_dpy = NULL; 1469848b8605Smrg _EGLContext *old_ctx; 1470848b8605Smrg _EGLSurface *old_dsurf, *old_rsurf; 1471b8e80941Smrg _EGLSurface *tmp_dsurf, *tmp_rsurf; 1472848b8605Smrg __DRIdrawable *ddraw, *rdraw; 1473848b8605Smrg __DRIcontext *cctx; 1474b8e80941Smrg EGLBoolean unbind; 1475b8e80941Smrg 1476b8e80941Smrg if (!dri2_dpy) 1477b8e80941Smrg return _eglError(EGL_NOT_INITIALIZED, "eglMakeCurrent"); 1478848b8605Smrg 1479848b8605Smrg /* make new bindings */ 1480b8e80941Smrg if (!_eglBindContext(ctx, dsurf, rsurf, &old_ctx, &old_dsurf, &old_rsurf)) { 1481b8e80941Smrg /* _eglBindContext already sets the EGL error (in _eglCheckMakeCurrent) */ 1482848b8605Smrg return EGL_FALSE; 1483b8e80941Smrg } 1484b8e80941Smrg 1485b8e80941Smrg if (old_ctx) { 1486b8e80941Smrg old_disp = old_ctx->Resource.Display; 1487b8e80941Smrg old_dri2_dpy = dri2_egl_display(old_disp); 1488b8e80941Smrg } 1489848b8605Smrg 1490848b8605Smrg /* flush before context switch */ 1491b8e80941Smrg if (old_ctx) 1492b8e80941Smrg dri2_gl_flush(); 1493848b8605Smrg 1494b8e80941Smrg ddraw = (dsurf) ? dri2_dpy->vtbl->get_dri_drawable(dsurf) : NULL; 1495b8e80941Smrg rdraw = (rsurf) ? dri2_dpy->vtbl->get_dri_drawable(rsurf) : NULL; 1496848b8605Smrg cctx = (dri2_ctx) ? dri2_ctx->dri_context : NULL; 1497848b8605Smrg 1498848b8605Smrg if (old_ctx) { 1499848b8605Smrg __DRIcontext *old_cctx = dri2_egl_context(old_ctx)->dri_context; 1500b8e80941Smrg 1501b8e80941Smrg if (old_dsurf) 1502b8e80941Smrg dri2_surf_update_fence_fd(old_ctx, disp, old_dsurf); 1503b8e80941Smrg 1504b8e80941Smrg /* Disable shared buffer mode */ 1505b8e80941Smrg if (old_dsurf && _eglSurfaceInSharedBufferMode(old_dsurf) && 1506b8e80941Smrg old_dri2_dpy->vtbl->set_shared_buffer_mode) { 1507b8e80941Smrg old_dri2_dpy->vtbl->set_shared_buffer_mode(old_disp, old_dsurf, false); 1508b8e80941Smrg } 1509b8e80941Smrg 1510848b8605Smrg dri2_dpy->core->unbindContext(old_cctx); 1511848b8605Smrg } 1512848b8605Smrg 1513b8e80941Smrg unbind = (cctx == NULL && ddraw == NULL && rdraw == NULL); 1514848b8605Smrg 1515b8e80941Smrg if (!unbind && !dri2_dpy->core->bindContext(cctx, ddraw, rdraw)) { 1516848b8605Smrg /* undo the previous _eglBindContext */ 1517b8e80941Smrg _eglBindContext(old_ctx, old_dsurf, old_rsurf, &ctx, &tmp_dsurf, &tmp_rsurf); 1518848b8605Smrg assert(&dri2_ctx->base == ctx && 1519b8e80941Smrg tmp_dsurf == dsurf && 1520b8e80941Smrg tmp_rsurf == rsurf); 1521b8e80941Smrg 1522b8e80941Smrg if (old_dsurf && _eglSurfaceInSharedBufferMode(old_dsurf) && 1523b8e80941Smrg old_dri2_dpy->vtbl->set_shared_buffer_mode) { 1524b8e80941Smrg old_dri2_dpy->vtbl->set_shared_buffer_mode(old_disp, old_dsurf, true); 1525b8e80941Smrg } 1526848b8605Smrg 1527848b8605Smrg _eglPutSurface(dsurf); 1528848b8605Smrg _eglPutSurface(rsurf); 1529848b8605Smrg _eglPutContext(ctx); 1530848b8605Smrg 1531848b8605Smrg _eglPutSurface(old_dsurf); 1532848b8605Smrg _eglPutSurface(old_rsurf); 1533848b8605Smrg _eglPutContext(old_ctx); 1534848b8605Smrg 1535b8e80941Smrg /* dri2_dpy->core->bindContext failed. We cannot tell for sure why, but 1536b8e80941Smrg * setting the error to EGL_BAD_MATCH is surely better than leaving it 1537b8e80941Smrg * as EGL_SUCCESS. 1538b8e80941Smrg */ 1539b8e80941Smrg return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); 1540b8e80941Smrg } 1541b8e80941Smrg 1542b8e80941Smrg dri2_destroy_surface(drv, disp, old_dsurf); 1543b8e80941Smrg dri2_destroy_surface(drv, disp, old_rsurf); 1544b8e80941Smrg 1545b8e80941Smrg if (!unbind) 1546b8e80941Smrg dri2_dpy->ref_count++; 1547b8e80941Smrg 1548b8e80941Smrg if (old_ctx) { 1549b8e80941Smrg dri2_destroy_context(drv, disp, old_ctx); 1550b8e80941Smrg dri2_display_release(old_disp); 1551b8e80941Smrg } 1552b8e80941Smrg 1553b8e80941Smrg if (dsurf && _eglSurfaceHasMutableRenderBuffer(dsurf) && 1554b8e80941Smrg dri2_dpy->vtbl->set_shared_buffer_mode) { 1555b8e80941Smrg /* Always update the shared buffer mode. This is obviously needed when 1556b8e80941Smrg * the active EGL_RENDER_BUFFER is EGL_SINGLE_BUFFER. When 1557b8e80941Smrg * EGL_RENDER_BUFFER is EGL_BACK_BUFFER, the update protects us in the 1558b8e80941Smrg * case where external non-EGL API may have changed window's shared 1559b8e80941Smrg * buffer mode since we last saw it. 1560b8e80941Smrg */ 1561b8e80941Smrg bool mode = (dsurf->ActiveRenderBuffer == EGL_SINGLE_BUFFER); 1562b8e80941Smrg dri2_dpy->vtbl->set_shared_buffer_mode(disp, dsurf, mode); 1563848b8605Smrg } 1564b8e80941Smrg 1565b8e80941Smrg return EGL_TRUE; 1566b8e80941Smrg} 1567b8e80941Smrg 1568b8e80941Smrg__DRIdrawable * 1569b8e80941Smrgdri2_surface_get_dri_drawable(_EGLSurface *surf) 1570b8e80941Smrg{ 1571b8e80941Smrg struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); 1572b8e80941Smrg 1573b8e80941Smrg return dri2_surf->dri_drawable; 1574848b8605Smrg} 1575848b8605Smrg 1576848b8605Smrg/* 1577848b8605Smrg * Called from eglGetProcAddress() via drv->API.GetProcAddress(). 1578848b8605Smrg */ 1579848b8605Smrgstatic _EGLProc 1580848b8605Smrgdri2_get_proc_address(_EGLDriver *drv, const char *procname) 1581848b8605Smrg{ 1582b8e80941Smrg return _glapi_get_proc_address(procname); 1583848b8605Smrg} 1584848b8605Smrg 1585848b8605Smrgstatic _EGLSurface* 1586b8e80941Smrgdri2_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp, 1587848b8605Smrg _EGLConfig *conf, void *native_window, 1588848b8605Smrg const EGLint *attrib_list) 1589848b8605Smrg{ 1590b8e80941Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1591b8e80941Smrg return dri2_dpy->vtbl->create_window_surface(drv, disp, conf, native_window, 1592848b8605Smrg attrib_list); 1593848b8605Smrg} 1594848b8605Smrg 1595848b8605Smrgstatic _EGLSurface* 1596b8e80941Smrgdri2_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *disp, 1597848b8605Smrg _EGLConfig *conf, void *native_pixmap, 1598848b8605Smrg const EGLint *attrib_list) 1599848b8605Smrg{ 1600b8e80941Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1601b8e80941Smrg return dri2_dpy->vtbl->create_pixmap_surface(drv, disp, conf, native_pixmap, 1602848b8605Smrg attrib_list); 1603848b8605Smrg} 1604848b8605Smrg 1605848b8605Smrgstatic _EGLSurface* 1606b8e80941Smrgdri2_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *disp, 1607848b8605Smrg _EGLConfig *conf, const EGLint *attrib_list) 1608848b8605Smrg{ 1609b8e80941Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1610b8e80941Smrg return dri2_dpy->vtbl->create_pbuffer_surface(drv, disp, conf, attrib_list); 1611848b8605Smrg} 1612848b8605Smrg 1613848b8605Smrgstatic EGLBoolean 1614b8e80941Smrgdri2_swap_interval(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf, 1615b8e80941Smrg EGLint interval) 1616848b8605Smrg{ 1617b8e80941Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1618b8e80941Smrg if (!dri2_dpy->vtbl->swap_interval) 1619b8e80941Smrg return EGL_TRUE; 1620b8e80941Smrg return dri2_dpy->vtbl->swap_interval(drv, disp, surf, interval); 1621848b8605Smrg} 1622848b8605Smrg 1623b8e80941Smrg/** 1624b8e80941Smrg * Asks the client API to flush any rendering to the drawable so that we can 1625b8e80941Smrg * do our swapbuffers. 1626b8e80941Smrg */ 1627b8e80941Smrgvoid 1628b8e80941Smrgdri2_flush_drawable_for_swapbuffers(_EGLDisplay *disp, _EGLSurface *draw) 1629848b8605Smrg{ 1630b8e80941Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1631b8e80941Smrg __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(draw); 1632b8e80941Smrg 1633b8e80941Smrg if (dri2_dpy->flush) { 1634b8e80941Smrg if (dri2_dpy->flush->base.version >= 4) { 1635b8e80941Smrg /* We know there's a current context because: 1636b8e80941Smrg * 1637b8e80941Smrg * "If surface is not bound to the calling thread’s current 1638b8e80941Smrg * context, an EGL_BAD_SURFACE error is generated." 1639b8e80941Smrg */ 1640b8e80941Smrg _EGLContext *ctx = _eglGetCurrentContext(); 1641b8e80941Smrg struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); 1642b8e80941Smrg 1643b8e80941Smrg /* From the EGL 1.4 spec (page 52): 1644b8e80941Smrg * 1645b8e80941Smrg * "The contents of ancillary buffers are always undefined 1646b8e80941Smrg * after calling eglSwapBuffers." 1647b8e80941Smrg */ 1648b8e80941Smrg dri2_dpy->flush->flush_with_flags(dri2_ctx->dri_context, 1649b8e80941Smrg dri_drawable, 1650b8e80941Smrg __DRI2_FLUSH_DRAWABLE | 1651b8e80941Smrg __DRI2_FLUSH_INVALIDATE_ANCILLARY, 1652b8e80941Smrg __DRI2_THROTTLE_SWAPBUFFER); 1653b8e80941Smrg } else { 1654b8e80941Smrg dri2_dpy->flush->flush(dri_drawable); 1655b8e80941Smrg } 1656b8e80941Smrg } 1657848b8605Smrg} 1658848b8605Smrg 1659848b8605Smrgstatic EGLBoolean 1660b8e80941Smrgdri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf) 1661848b8605Smrg{ 1662b8e80941Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1663b8e80941Smrg _EGLContext *ctx = _eglGetCurrentContext(); 1664b8e80941Smrg 1665b8e80941Smrg if (ctx && surf) 1666b8e80941Smrg dri2_surf_update_fence_fd(ctx, disp, surf); 1667b8e80941Smrg return dri2_dpy->vtbl->swap_buffers(drv, disp, surf); 1668848b8605Smrg} 1669848b8605Smrg 1670848b8605Smrgstatic EGLBoolean 1671b8e80941Smrgdri2_swap_buffers_with_damage(_EGLDriver *drv, _EGLDisplay *disp, 1672848b8605Smrg _EGLSurface *surf, 1673848b8605Smrg const EGLint *rects, EGLint n_rects) 1674848b8605Smrg{ 1675b8e80941Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1676b8e80941Smrg _EGLContext *ctx = _eglGetCurrentContext(); 1677b8e80941Smrg 1678b8e80941Smrg if (ctx && surf) 1679b8e80941Smrg dri2_surf_update_fence_fd(ctx, disp, surf); 1680b8e80941Smrg return dri2_dpy->vtbl->swap_buffers_with_damage(drv, disp, surf, 1681848b8605Smrg rects, n_rects); 1682848b8605Smrg} 1683848b8605Smrg 1684848b8605Smrgstatic EGLBoolean 1685b8e80941Smrgdri2_swap_buffers_region(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf, 1686848b8605Smrg EGLint numRects, const EGLint *rects) 1687848b8605Smrg{ 1688b8e80941Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1689b8e80941Smrg return dri2_dpy->vtbl->swap_buffers_region(drv, disp, surf, numRects, rects); 1690b8e80941Smrg} 1691b8e80941Smrg 1692b8e80941Smrgstatic EGLBoolean 1693b8e80941Smrgdri2_set_damage_region(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf, 1694b8e80941Smrg EGLint *rects, EGLint n_rects) 1695b8e80941Smrg{ 1696b8e80941Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1697b8e80941Smrg return dri2_dpy->vtbl->set_damage_region(drv, disp, surf, rects, n_rects); 1698848b8605Smrg} 1699848b8605Smrg 1700848b8605Smrgstatic EGLBoolean 1701b8e80941Smrgdri2_post_sub_buffer(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf, 1702848b8605Smrg EGLint x, EGLint y, EGLint width, EGLint height) 1703848b8605Smrg{ 1704b8e80941Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1705b8e80941Smrg return dri2_dpy->vtbl->post_sub_buffer(drv, disp, surf, x, y, width, height); 1706848b8605Smrg} 1707848b8605Smrg 1708848b8605Smrgstatic EGLBoolean 1709b8e80941Smrgdri2_copy_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf, 1710848b8605Smrg void *native_pixmap_target) 1711848b8605Smrg{ 1712b8e80941Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1713b8e80941Smrg return dri2_dpy->vtbl->copy_buffers(drv, disp, surf, native_pixmap_target); 1714848b8605Smrg} 1715848b8605Smrg 1716848b8605Smrgstatic EGLint 1717b8e80941Smrgdri2_query_buffer_age(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf) 1718848b8605Smrg{ 1719b8e80941Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1720b8e80941Smrg return dri2_dpy->vtbl->query_buffer_age(drv, disp, surf); 1721848b8605Smrg} 1722848b8605Smrg 1723848b8605Smrgstatic EGLBoolean 1724848b8605Smrgdri2_wait_client(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx) 1725848b8605Smrg{ 1726848b8605Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1727b8e80941Smrg _EGLSurface *surf = ctx->DrawSurface; 1728b8e80941Smrg __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(surf); 1729848b8605Smrg 1730848b8605Smrg (void) drv; 1731848b8605Smrg 1732848b8605Smrg /* FIXME: If EGL allows frontbuffer rendering for window surfaces, 1733848b8605Smrg * we need to copy fake to real here.*/ 1734848b8605Smrg 1735848b8605Smrg if (dri2_dpy->flush != NULL) 1736b8e80941Smrg dri2_dpy->flush->flush(dri_drawable); 1737848b8605Smrg 1738848b8605Smrg return EGL_TRUE; 1739848b8605Smrg} 1740848b8605Smrg 1741848b8605Smrgstatic EGLBoolean 1742848b8605Smrgdri2_wait_native(_EGLDriver *drv, _EGLDisplay *disp, EGLint engine) 1743848b8605Smrg{ 1744848b8605Smrg (void) drv; 1745848b8605Smrg (void) disp; 1746848b8605Smrg 1747848b8605Smrg if (engine != EGL_CORE_NATIVE_ENGINE) 1748848b8605Smrg return _eglError(EGL_BAD_PARAMETER, "eglWaitNative"); 1749848b8605Smrg /* glXWaitX(); */ 1750848b8605Smrg 1751848b8605Smrg return EGL_TRUE; 1752848b8605Smrg} 1753848b8605Smrg 1754848b8605Smrgstatic EGLBoolean 1755848b8605Smrgdri2_bind_tex_image(_EGLDriver *drv, 1756b8e80941Smrg _EGLDisplay *disp, _EGLSurface *surf, EGLint buffer) 1757848b8605Smrg{ 1758848b8605Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1759848b8605Smrg struct dri2_egl_context *dri2_ctx; 1760848b8605Smrg _EGLContext *ctx; 1761848b8605Smrg GLint format, target; 1762b8e80941Smrg __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(surf); 1763848b8605Smrg 1764848b8605Smrg ctx = _eglGetCurrentContext(); 1765848b8605Smrg dri2_ctx = dri2_egl_context(ctx); 1766848b8605Smrg 1767848b8605Smrg if (!_eglBindTexImage(drv, disp, surf, buffer)) 1768848b8605Smrg return EGL_FALSE; 1769848b8605Smrg 1770b8e80941Smrg switch (surf->TextureFormat) { 1771848b8605Smrg case EGL_TEXTURE_RGB: 1772848b8605Smrg format = __DRI_TEXTURE_FORMAT_RGB; 1773848b8605Smrg break; 1774848b8605Smrg case EGL_TEXTURE_RGBA: 1775848b8605Smrg format = __DRI_TEXTURE_FORMAT_RGBA; 1776848b8605Smrg break; 1777848b8605Smrg default: 1778b8e80941Smrg assert(!"Unexpected texture format in dri2_bind_tex_image()"); 1779b8e80941Smrg format = __DRI_TEXTURE_FORMAT_RGBA; 1780848b8605Smrg } 1781848b8605Smrg 1782b8e80941Smrg switch (surf->TextureTarget) { 1783848b8605Smrg case EGL_TEXTURE_2D: 1784848b8605Smrg target = GL_TEXTURE_2D; 1785848b8605Smrg break; 1786848b8605Smrg default: 1787b8e80941Smrg target = GL_TEXTURE_2D; 1788b8e80941Smrg assert(!"Unexpected texture target in dri2_bind_tex_image()"); 1789848b8605Smrg } 1790848b8605Smrg 1791b8e80941Smrg dri2_dpy->tex_buffer->setTexBuffer2(dri2_ctx->dri_context, 1792b8e80941Smrg target, format, 1793b8e80941Smrg dri_drawable); 1794848b8605Smrg 1795848b8605Smrg return EGL_TRUE; 1796848b8605Smrg} 1797848b8605Smrg 1798848b8605Smrgstatic EGLBoolean 1799848b8605Smrgdri2_release_tex_image(_EGLDriver *drv, 1800b8e80941Smrg _EGLDisplay *disp, _EGLSurface *surf, EGLint buffer) 1801848b8605Smrg{ 1802848b8605Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1803848b8605Smrg struct dri2_egl_context *dri2_ctx; 1804848b8605Smrg _EGLContext *ctx; 1805848b8605Smrg GLint target; 1806b8e80941Smrg __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(surf); 1807848b8605Smrg 1808848b8605Smrg ctx = _eglGetCurrentContext(); 1809848b8605Smrg dri2_ctx = dri2_egl_context(ctx); 1810848b8605Smrg 1811848b8605Smrg if (!_eglReleaseTexImage(drv, disp, surf, buffer)) 1812848b8605Smrg return EGL_FALSE; 1813848b8605Smrg 1814b8e80941Smrg switch (surf->TextureTarget) { 1815848b8605Smrg case EGL_TEXTURE_2D: 1816848b8605Smrg target = GL_TEXTURE_2D; 1817848b8605Smrg break; 1818848b8605Smrg default: 1819b8e80941Smrg assert(!"missing texture target"); 1820848b8605Smrg } 1821848b8605Smrg 1822848b8605Smrg if (dri2_dpy->tex_buffer->base.version >= 3 && 1823848b8605Smrg dri2_dpy->tex_buffer->releaseTexBuffer != NULL) { 1824b8e80941Smrg dri2_dpy->tex_buffer->releaseTexBuffer(dri2_ctx->dri_context, 1825b8e80941Smrg target, dri_drawable); 1826848b8605Smrg } 1827848b8605Smrg 1828848b8605Smrg return EGL_TRUE; 1829848b8605Smrg} 1830848b8605Smrg 1831848b8605Smrgstatic _EGLImage* 1832b8e80941Smrgdri2_create_image(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx, 1833848b8605Smrg EGLenum target, EGLClientBuffer buffer, 1834848b8605Smrg const EGLint *attr_list) 1835848b8605Smrg{ 1836b8e80941Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1837b8e80941Smrg return dri2_dpy->vtbl->create_image(drv, disp, ctx, target, buffer, 1838848b8605Smrg attr_list); 1839848b8605Smrg} 1840848b8605Smrg 1841848b8605Smrgstatic _EGLImage * 1842848b8605Smrgdri2_create_image_from_dri(_EGLDisplay *disp, __DRIimage *dri_image) 1843848b8605Smrg{ 1844848b8605Smrg struct dri2_egl_image *dri2_img; 1845848b8605Smrg 1846848b8605Smrg if (dri_image == NULL) { 1847848b8605Smrg _eglError(EGL_BAD_ALLOC, "dri2_create_image"); 1848848b8605Smrg return NULL; 1849848b8605Smrg } 1850848b8605Smrg 1851848b8605Smrg dri2_img = malloc(sizeof *dri2_img); 1852848b8605Smrg if (!dri2_img) { 1853848b8605Smrg _eglError(EGL_BAD_ALLOC, "dri2_create_image"); 1854848b8605Smrg return NULL; 1855848b8605Smrg } 1856848b8605Smrg 1857b8e80941Smrg _eglInitImage(&dri2_img->base, disp); 1858848b8605Smrg 1859848b8605Smrg dri2_img->dri_image = dri_image; 1860848b8605Smrg 1861848b8605Smrg return &dri2_img->base; 1862848b8605Smrg} 1863848b8605Smrg 1864b8e80941Smrg/** 1865b8e80941Smrg * Translate a DRI Image extension error code into an EGL error code. 1866b8e80941Smrg */ 1867b8e80941Smrgstatic EGLint 1868b8e80941Smrgegl_error_from_dri_image_error(int dri_error) 1869b8e80941Smrg{ 1870b8e80941Smrg switch (dri_error) { 1871b8e80941Smrg case __DRI_IMAGE_ERROR_SUCCESS: 1872b8e80941Smrg return EGL_SUCCESS; 1873b8e80941Smrg case __DRI_IMAGE_ERROR_BAD_ALLOC: 1874b8e80941Smrg return EGL_BAD_ALLOC; 1875b8e80941Smrg case __DRI_IMAGE_ERROR_BAD_MATCH: 1876b8e80941Smrg return EGL_BAD_MATCH; 1877b8e80941Smrg case __DRI_IMAGE_ERROR_BAD_PARAMETER: 1878b8e80941Smrg return EGL_BAD_PARAMETER; 1879b8e80941Smrg case __DRI_IMAGE_ERROR_BAD_ACCESS: 1880b8e80941Smrg return EGL_BAD_ACCESS; 1881b8e80941Smrg default: 1882b8e80941Smrg assert(!"unknown dri_error code"); 1883b8e80941Smrg return EGL_BAD_ALLOC; 1884b8e80941Smrg } 1885b8e80941Smrg} 1886b8e80941Smrg 1887848b8605Smrgstatic _EGLImage * 1888848b8605Smrgdri2_create_image_khr_renderbuffer(_EGLDisplay *disp, _EGLContext *ctx, 1889b8e80941Smrg EGLClientBuffer buffer, 1890b8e80941Smrg const EGLint *attr_list) 1891848b8605Smrg{ 1892848b8605Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1893848b8605Smrg struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); 1894848b8605Smrg GLuint renderbuffer = (GLuint) (uintptr_t) buffer; 1895848b8605Smrg __DRIimage *dri_image; 1896848b8605Smrg 1897848b8605Smrg if (renderbuffer == 0) { 1898848b8605Smrg _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr"); 1899848b8605Smrg return EGL_NO_IMAGE_KHR; 1900848b8605Smrg } 1901848b8605Smrg 1902b8e80941Smrg if (!disp->Extensions.KHR_gl_renderbuffer_image) { 1903b8e80941Smrg _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr"); 1904b8e80941Smrg return EGL_NO_IMAGE_KHR; 1905b8e80941Smrg } 1906848b8605Smrg 1907b8e80941Smrg if (dri2_dpy->image->base.version >= 17 && 1908b8e80941Smrg dri2_dpy->image->createImageFromRenderbuffer2) { 1909b8e80941Smrg unsigned error = ~0; 1910848b8605Smrg 1911b8e80941Smrg dri_image = dri2_dpy->image->createImageFromRenderbuffer2( 1912b8e80941Smrg dri2_ctx->dri_context, renderbuffer, NULL, &error); 1913848b8605Smrg 1914b8e80941Smrg assert(!!dri_image == (error == __DRI_IMAGE_ERROR_SUCCESS)); 1915848b8605Smrg 1916b8e80941Smrg if (!dri_image) { 1917b8e80941Smrg _eglError(egl_error_from_dri_image_error(error), "dri2_create_image_khr"); 1918b8e80941Smrg return EGL_NO_IMAGE_KHR; 1919b8e80941Smrg } 1920b8e80941Smrg } else { 1921b8e80941Smrg dri_image = dri2_dpy->image->createImageFromRenderbuffer( 1922b8e80941Smrg dri2_ctx->dri_context, renderbuffer, NULL); 1923b8e80941Smrg if (!dri_image) { 1924b8e80941Smrg _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr"); 1925b8e80941Smrg return EGL_NO_IMAGE_KHR; 1926b8e80941Smrg } 1927848b8605Smrg } 1928848b8605Smrg 1929848b8605Smrg return dri2_create_image_from_dri(disp, dri_image); 1930848b8605Smrg} 1931848b8605Smrg 1932848b8605Smrg#ifdef HAVE_WAYLAND_PLATFORM 1933848b8605Smrg 1934848b8605Smrg/* This structure describes how a wl_buffer maps to one or more 1935848b8605Smrg * __DRIimages. A wl_drm_buffer stores the wl_drm format code and the 1936848b8605Smrg * offsets and strides of the planes in the buffer. This table maps a 1937848b8605Smrg * wl_drm format code to a description of the planes in the buffer 1938848b8605Smrg * that lets us create a __DRIimage for each of the planes. */ 1939848b8605Smrg 1940848b8605Smrgstatic const struct wl_drm_components_descriptor { 1941848b8605Smrg uint32_t dri_components; 1942848b8605Smrg EGLint components; 1943848b8605Smrg int nplanes; 1944848b8605Smrg} wl_drm_components[] = { 1945848b8605Smrg { __DRI_IMAGE_COMPONENTS_RGB, EGL_TEXTURE_RGB, 1 }, 1946848b8605Smrg { __DRI_IMAGE_COMPONENTS_RGBA, EGL_TEXTURE_RGBA, 1 }, 1947848b8605Smrg { __DRI_IMAGE_COMPONENTS_Y_U_V, EGL_TEXTURE_Y_U_V_WL, 3 }, 1948848b8605Smrg { __DRI_IMAGE_COMPONENTS_Y_UV, EGL_TEXTURE_Y_UV_WL, 2 }, 1949848b8605Smrg { __DRI_IMAGE_COMPONENTS_Y_XUXV, EGL_TEXTURE_Y_XUXV_WL, 2 }, 1950848b8605Smrg}; 1951848b8605Smrg 1952848b8605Smrgstatic _EGLImage * 1953848b8605Smrgdri2_create_image_wayland_wl_buffer(_EGLDisplay *disp, _EGLContext *ctx, 1954b8e80941Smrg EGLClientBuffer _buffer, 1955b8e80941Smrg const EGLint *attr_list) 1956848b8605Smrg{ 1957848b8605Smrg struct wl_drm_buffer *buffer; 1958848b8605Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1959848b8605Smrg const struct wl_drm_components_descriptor *f; 1960848b8605Smrg __DRIimage *dri_image; 1961848b8605Smrg _EGLImageAttribs attrs; 1962848b8605Smrg int32_t plane; 1963848b8605Smrg 1964848b8605Smrg buffer = wayland_drm_buffer_get(dri2_dpy->wl_server_drm, 1965848b8605Smrg (struct wl_resource *) _buffer); 1966848b8605Smrg if (!buffer) 1967848b8605Smrg return NULL; 1968848b8605Smrg 1969b8e80941Smrg if (!_eglParseImageAttribList(&attrs, disp, attr_list)) 1970848b8605Smrg return NULL; 1971848b8605Smrg 1972b8e80941Smrg plane = attrs.PlaneWL; 1973848b8605Smrg f = buffer->driver_format; 1974848b8605Smrg if (plane < 0 || plane >= f->nplanes) { 1975848b8605Smrg _eglError(EGL_BAD_PARAMETER, 1976848b8605Smrg "dri2_create_image_wayland_wl_buffer (plane out of bounds)"); 1977848b8605Smrg return NULL; 1978848b8605Smrg } 1979848b8605Smrg 1980848b8605Smrg dri_image = dri2_dpy->image->fromPlanar(buffer->driver_buffer, plane, NULL); 1981b8e80941Smrg if (dri_image == NULL && plane == 0) 1982b8e80941Smrg dri_image = dri2_dpy->image->dupImage(buffer->driver_buffer, NULL); 1983848b8605Smrg if (dri_image == NULL) { 1984848b8605Smrg _eglError(EGL_BAD_PARAMETER, "dri2_create_image_wayland_wl_buffer"); 1985848b8605Smrg return NULL; 1986848b8605Smrg } 1987848b8605Smrg 1988848b8605Smrg return dri2_create_image_from_dri(disp, dri_image); 1989848b8605Smrg} 1990848b8605Smrg#endif 1991848b8605Smrg 1992848b8605Smrgstatic EGLBoolean 1993b8e80941Smrgdri2_get_sync_values_chromium(_EGLDisplay *disp, _EGLSurface *surf, 1994848b8605Smrg EGLuint64KHR *ust, EGLuint64KHR *msc, 1995848b8605Smrg EGLuint64KHR *sbc) 1996848b8605Smrg{ 1997b8e80941Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1998b8e80941Smrg return dri2_dpy->vtbl->get_sync_values(disp, surf, ust, msc, sbc); 1999848b8605Smrg} 2000848b8605Smrg 2001848b8605Smrg/** 2002848b8605Smrg * Set the error code after a call to 2003848b8605Smrg * dri2_egl_image::dri_image::createImageFromTexture. 2004848b8605Smrg */ 2005848b8605Smrgstatic void 2006848b8605Smrgdri2_create_image_khr_texture_error(int dri_error) 2007848b8605Smrg{ 2008b8e80941Smrg EGLint egl_error = egl_error_from_dri_image_error(dri_error); 2009848b8605Smrg 2010b8e80941Smrg if (egl_error != EGL_SUCCESS) 2011b8e80941Smrg _eglError(egl_error, "dri2_create_image_khr_texture"); 2012848b8605Smrg} 2013848b8605Smrg 2014848b8605Smrgstatic _EGLImage * 2015848b8605Smrgdri2_create_image_khr_texture(_EGLDisplay *disp, _EGLContext *ctx, 2016b8e80941Smrg EGLenum target, 2017b8e80941Smrg EGLClientBuffer buffer, 2018b8e80941Smrg const EGLint *attr_list) 2019848b8605Smrg{ 2020848b8605Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2021848b8605Smrg struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); 2022848b8605Smrg struct dri2_egl_image *dri2_img; 2023848b8605Smrg GLuint texture = (GLuint) (uintptr_t) buffer; 2024848b8605Smrg _EGLImageAttribs attrs; 2025848b8605Smrg GLuint depth; 2026848b8605Smrg GLenum gl_target; 2027848b8605Smrg unsigned error; 2028848b8605Smrg 2029848b8605Smrg if (texture == 0) { 2030848b8605Smrg _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr"); 2031848b8605Smrg return EGL_NO_IMAGE_KHR; 2032848b8605Smrg } 2033848b8605Smrg 2034b8e80941Smrg if (!_eglParseImageAttribList(&attrs, disp, attr_list)) 2035848b8605Smrg return EGL_NO_IMAGE_KHR; 2036848b8605Smrg 2037848b8605Smrg switch (target) { 2038848b8605Smrg case EGL_GL_TEXTURE_2D_KHR: 2039b8e80941Smrg if (!disp->Extensions.KHR_gl_texture_2D_image) { 2040b8e80941Smrg _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr"); 2041b8e80941Smrg return EGL_NO_IMAGE_KHR; 2042b8e80941Smrg } 2043848b8605Smrg depth = 0; 2044848b8605Smrg gl_target = GL_TEXTURE_2D; 2045848b8605Smrg break; 2046848b8605Smrg case EGL_GL_TEXTURE_3D_KHR: 2047b8e80941Smrg if (!disp->Extensions.KHR_gl_texture_3D_image) { 2048b8e80941Smrg _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr"); 2049b8e80941Smrg return EGL_NO_IMAGE_KHR; 2050b8e80941Smrg } 2051b8e80941Smrg 2052848b8605Smrg depth = attrs.GLTextureZOffset; 2053848b8605Smrg gl_target = GL_TEXTURE_3D; 2054848b8605Smrg break; 2055848b8605Smrg case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR: 2056848b8605Smrg case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR: 2057848b8605Smrg case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR: 2058848b8605Smrg case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR: 2059848b8605Smrg case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR: 2060848b8605Smrg case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR: 2061b8e80941Smrg if (!disp->Extensions.KHR_gl_texture_cubemap_image) { 2062b8e80941Smrg _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr"); 2063b8e80941Smrg return EGL_NO_IMAGE_KHR; 2064b8e80941Smrg } 2065b8e80941Smrg 2066848b8605Smrg depth = target - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR; 2067848b8605Smrg gl_target = GL_TEXTURE_CUBE_MAP; 2068848b8605Smrg break; 2069848b8605Smrg default: 2070b8e80941Smrg unreachable("Unexpected target in dri2_create_image_khr_texture()"); 2071848b8605Smrg return EGL_NO_IMAGE_KHR; 2072848b8605Smrg } 2073848b8605Smrg 2074848b8605Smrg dri2_img = malloc(sizeof *dri2_img); 2075848b8605Smrg if (!dri2_img) { 2076848b8605Smrg _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr"); 2077848b8605Smrg return EGL_NO_IMAGE_KHR; 2078848b8605Smrg } 2079848b8605Smrg 2080b8e80941Smrg _eglInitImage(&dri2_img->base, disp); 2081848b8605Smrg 2082848b8605Smrg dri2_img->dri_image = 2083848b8605Smrg dri2_dpy->image->createImageFromTexture(dri2_ctx->dri_context, 2084848b8605Smrg gl_target, 2085848b8605Smrg texture, 2086848b8605Smrg depth, 2087848b8605Smrg attrs.GLTextureLevel, 2088848b8605Smrg &error, 2089848b8605Smrg dri2_img); 2090848b8605Smrg dri2_create_image_khr_texture_error(error); 2091848b8605Smrg 2092848b8605Smrg if (!dri2_img->dri_image) { 2093848b8605Smrg free(dri2_img); 2094848b8605Smrg return EGL_NO_IMAGE_KHR; 2095848b8605Smrg } 2096848b8605Smrg return &dri2_img->base; 2097848b8605Smrg} 2098848b8605Smrg 2099b8e80941Smrgstatic EGLBoolean 2100b8e80941Smrgdri2_query_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf, 2101b8e80941Smrg EGLint attribute, EGLint *value) 2102b8e80941Smrg{ 2103b8e80941Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2104b8e80941Smrg if (!dri2_dpy->vtbl->query_surface) 2105b8e80941Smrg return _eglQuerySurface(drv, disp, surf, attribute, value); 2106b8e80941Smrg return dri2_dpy->vtbl->query_surface(drv, disp, surf, attribute, value); 2107b8e80941Smrg} 2108b8e80941Smrg 2109848b8605Smrgstatic struct wl_buffer* 2110b8e80941Smrgdri2_create_wayland_buffer_from_image(_EGLDriver *drv, _EGLDisplay *disp, 2111848b8605Smrg _EGLImage *img) 2112848b8605Smrg{ 2113b8e80941Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2114b8e80941Smrg return dri2_dpy->vtbl->create_wayland_buffer_from_image(drv, disp, img); 2115b8e80941Smrg} 2116b8e80941Smrg 2117b8e80941Smrg#ifdef HAVE_LIBDRM 2118b8e80941Smrgstatic _EGLImage * 2119b8e80941Smrgdri2_create_image_mesa_drm_buffer(_EGLDisplay *disp, _EGLContext *ctx, 2120b8e80941Smrg EGLClientBuffer buffer, const EGLint *attr_list) 2121b8e80941Smrg{ 2122b8e80941Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2123b8e80941Smrg EGLint format, name, pitch; 2124b8e80941Smrg _EGLImageAttribs attrs; 2125b8e80941Smrg __DRIimage *dri_image; 2126b8e80941Smrg 2127b8e80941Smrg name = (EGLint) (uintptr_t) buffer; 2128b8e80941Smrg 2129b8e80941Smrg if (!_eglParseImageAttribList(&attrs, disp, attr_list)) 2130b8e80941Smrg return NULL; 2131b8e80941Smrg 2132b8e80941Smrg if (attrs.Width <= 0 || attrs.Height <= 0 || 2133b8e80941Smrg attrs.DRMBufferStrideMESA <= 0) { 2134b8e80941Smrg _eglError(EGL_BAD_PARAMETER, 2135b8e80941Smrg "bad width, height or stride"); 2136b8e80941Smrg return NULL; 2137b8e80941Smrg } 2138b8e80941Smrg 2139b8e80941Smrg switch (attrs.DRMBufferFormatMESA) { 2140b8e80941Smrg case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA: 2141b8e80941Smrg format = __DRI_IMAGE_FORMAT_ARGB8888; 2142b8e80941Smrg pitch = attrs.DRMBufferStrideMESA; 2143b8e80941Smrg break; 2144b8e80941Smrg default: 2145b8e80941Smrg _eglError(EGL_BAD_PARAMETER, 2146b8e80941Smrg "dri2_create_image_khr: unsupported pixmap depth"); 2147b8e80941Smrg return NULL; 2148b8e80941Smrg } 2149b8e80941Smrg 2150b8e80941Smrg dri_image = 2151b8e80941Smrg dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen, 2152b8e80941Smrg attrs.Width, 2153b8e80941Smrg attrs.Height, 2154b8e80941Smrg format, 2155b8e80941Smrg name, 2156b8e80941Smrg pitch, 2157b8e80941Smrg NULL); 2158b8e80941Smrg 2159b8e80941Smrg return dri2_create_image_from_dri(disp, dri_image); 2160848b8605Smrg} 2161848b8605Smrg 2162848b8605Smrgstatic EGLBoolean 2163848b8605Smrgdri2_check_dma_buf_attribs(const _EGLImageAttribs *attrs) 2164848b8605Smrg{ 2165848b8605Smrg /** 2166848b8605Smrg * The spec says: 2167848b8605Smrg * 2168848b8605Smrg * "Required attributes and their values are as follows: 2169848b8605Smrg * 2170848b8605Smrg * * EGL_WIDTH & EGL_HEIGHT: The logical dimensions of the buffer in pixels 2171848b8605Smrg * 2172848b8605Smrg * * EGL_LINUX_DRM_FOURCC_EXT: The pixel format of the buffer, as specified 2173848b8605Smrg * by drm_fourcc.h and used as the pixel_format parameter of the 2174848b8605Smrg * drm_mode_fb_cmd2 ioctl." 2175848b8605Smrg * 2176848b8605Smrg * and 2177848b8605Smrg * 2178848b8605Smrg * "* If <target> is EGL_LINUX_DMA_BUF_EXT, and the list of attributes is 2179848b8605Smrg * incomplete, EGL_BAD_PARAMETER is generated." 2180848b8605Smrg */ 2181848b8605Smrg if (attrs->Width <= 0 || attrs->Height <= 0 || 2182b8e80941Smrg !attrs->DMABufFourCC.IsPresent) 2183b8e80941Smrg return _eglError(EGL_BAD_PARAMETER, "attribute(s) missing"); 2184848b8605Smrg 2185848b8605Smrg /** 2186848b8605Smrg * Also: 2187848b8605Smrg * 2188848b8605Smrg * "If <target> is EGL_LINUX_DMA_BUF_EXT and one or more of the values 2189848b8605Smrg * specified for a plane's pitch or offset isn't supported by EGL, 2190848b8605Smrg * EGL_BAD_ACCESS is generated." 2191848b8605Smrg */ 2192b8e80941Smrg for (unsigned i = 0; i < ARRAY_SIZE(attrs->DMABufPlanePitches); ++i) { 2193848b8605Smrg if (attrs->DMABufPlanePitches[i].IsPresent && 2194b8e80941Smrg attrs->DMABufPlanePitches[i].Value <= 0) 2195b8e80941Smrg return _eglError(EGL_BAD_ACCESS, "invalid pitch"); 2196b8e80941Smrg } 2197b8e80941Smrg 2198b8e80941Smrg /** 2199b8e80941Smrg * If <target> is EGL_LINUX_DMA_BUF_EXT, both or neither of the following 2200b8e80941Smrg * attribute values may be given. 2201b8e80941Smrg * 2202b8e80941Smrg * This is referring to EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT and 2203b8e80941Smrg * EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT, and the same for other planes. 2204b8e80941Smrg */ 2205b8e80941Smrg for (unsigned i = 0; i < DMA_BUF_MAX_PLANES; ++i) { 2206b8e80941Smrg if (attrs->DMABufPlaneModifiersLo[i].IsPresent != 2207b8e80941Smrg attrs->DMABufPlaneModifiersHi[i].IsPresent) 2208b8e80941Smrg return _eglError(EGL_BAD_PARAMETER, "modifier attribute lo or hi missing"); 2209b8e80941Smrg } 2210b8e80941Smrg 2211b8e80941Smrg /* Although the EGL_EXT_image_dma_buf_import_modifiers spec doesn't 2212b8e80941Smrg * mandate it, we only accept the same modifier across all planes. */ 2213b8e80941Smrg for (unsigned i = 1; i < DMA_BUF_MAX_PLANES; ++i) { 2214b8e80941Smrg if (attrs->DMABufPlaneFds[i].IsPresent) { 2215b8e80941Smrg if ((attrs->DMABufPlaneModifiersLo[0].IsPresent != 2216b8e80941Smrg attrs->DMABufPlaneModifiersLo[i].IsPresent) || 2217b8e80941Smrg (attrs->DMABufPlaneModifiersLo[0].Value != 2218b8e80941Smrg attrs->DMABufPlaneModifiersLo[i].Value) || 2219b8e80941Smrg (attrs->DMABufPlaneModifiersHi[0].Value != 2220b8e80941Smrg attrs->DMABufPlaneModifiersHi[i].Value)) 2221b8e80941Smrg return _eglError(EGL_BAD_PARAMETER, "modifier attributes not equal"); 2222848b8605Smrg } 2223848b8605Smrg } 2224848b8605Smrg 2225848b8605Smrg return EGL_TRUE; 2226848b8605Smrg} 2227848b8605Smrg 2228b8e80941Smrg/* Returns the total number of planes for the format or zero if it isn't a 2229b8e80941Smrg * valid fourcc format. 2230b8e80941Smrg */ 2231848b8605Smrgstatic unsigned 2232b8e80941Smrgdri2_num_fourcc_format_planes(EGLint format) 2233848b8605Smrg{ 2234b8e80941Smrg switch (format) { 2235b8e80941Smrg case DRM_FORMAT_R8: 2236b8e80941Smrg case DRM_FORMAT_RG88: 2237b8e80941Smrg case DRM_FORMAT_GR88: 2238b8e80941Smrg case DRM_FORMAT_R16: 2239b8e80941Smrg case DRM_FORMAT_GR1616: 2240848b8605Smrg case DRM_FORMAT_RGB332: 2241848b8605Smrg case DRM_FORMAT_BGR233: 2242848b8605Smrg case DRM_FORMAT_XRGB4444: 2243848b8605Smrg case DRM_FORMAT_XBGR4444: 2244848b8605Smrg case DRM_FORMAT_RGBX4444: 2245848b8605Smrg case DRM_FORMAT_BGRX4444: 2246848b8605Smrg case DRM_FORMAT_ARGB4444: 2247848b8605Smrg case DRM_FORMAT_ABGR4444: 2248848b8605Smrg case DRM_FORMAT_RGBA4444: 2249848b8605Smrg case DRM_FORMAT_BGRA4444: 2250848b8605Smrg case DRM_FORMAT_XRGB1555: 2251848b8605Smrg case DRM_FORMAT_XBGR1555: 2252848b8605Smrg case DRM_FORMAT_RGBX5551: 2253848b8605Smrg case DRM_FORMAT_BGRX5551: 2254848b8605Smrg case DRM_FORMAT_ARGB1555: 2255848b8605Smrg case DRM_FORMAT_ABGR1555: 2256848b8605Smrg case DRM_FORMAT_RGBA5551: 2257848b8605Smrg case DRM_FORMAT_BGRA5551: 2258848b8605Smrg case DRM_FORMAT_RGB565: 2259848b8605Smrg case DRM_FORMAT_BGR565: 2260848b8605Smrg case DRM_FORMAT_RGB888: 2261848b8605Smrg case DRM_FORMAT_BGR888: 2262848b8605Smrg case DRM_FORMAT_XRGB8888: 2263848b8605Smrg case DRM_FORMAT_XBGR8888: 2264848b8605Smrg case DRM_FORMAT_RGBX8888: 2265848b8605Smrg case DRM_FORMAT_BGRX8888: 2266848b8605Smrg case DRM_FORMAT_ARGB8888: 2267848b8605Smrg case DRM_FORMAT_ABGR8888: 2268848b8605Smrg case DRM_FORMAT_RGBA8888: 2269848b8605Smrg case DRM_FORMAT_BGRA8888: 2270848b8605Smrg case DRM_FORMAT_XRGB2101010: 2271848b8605Smrg case DRM_FORMAT_XBGR2101010: 2272848b8605Smrg case DRM_FORMAT_RGBX1010102: 2273848b8605Smrg case DRM_FORMAT_BGRX1010102: 2274848b8605Smrg case DRM_FORMAT_ARGB2101010: 2275848b8605Smrg case DRM_FORMAT_ABGR2101010: 2276848b8605Smrg case DRM_FORMAT_RGBA1010102: 2277848b8605Smrg case DRM_FORMAT_BGRA1010102: 2278848b8605Smrg case DRM_FORMAT_YUYV: 2279848b8605Smrg case DRM_FORMAT_YVYU: 2280848b8605Smrg case DRM_FORMAT_UYVY: 2281848b8605Smrg case DRM_FORMAT_VYUY: 2282b8e80941Smrg case DRM_FORMAT_AYUV: 2283b8e80941Smrg case DRM_FORMAT_XYUV8888: 2284b8e80941Smrg return 1; 2285b8e80941Smrg 2286848b8605Smrg case DRM_FORMAT_NV12: 2287848b8605Smrg case DRM_FORMAT_NV21: 2288848b8605Smrg case DRM_FORMAT_NV16: 2289848b8605Smrg case DRM_FORMAT_NV61: 2290b8e80941Smrg case DRM_FORMAT_P010: 2291b8e80941Smrg case DRM_FORMAT_P012: 2292b8e80941Smrg case DRM_FORMAT_P016: 2293b8e80941Smrg return 2; 2294b8e80941Smrg 2295848b8605Smrg case DRM_FORMAT_YUV410: 2296848b8605Smrg case DRM_FORMAT_YVU410: 2297848b8605Smrg case DRM_FORMAT_YUV411: 2298848b8605Smrg case DRM_FORMAT_YVU411: 2299848b8605Smrg case DRM_FORMAT_YUV420: 2300848b8605Smrg case DRM_FORMAT_YVU420: 2301848b8605Smrg case DRM_FORMAT_YUV422: 2302848b8605Smrg case DRM_FORMAT_YVU422: 2303848b8605Smrg case DRM_FORMAT_YUV444: 2304848b8605Smrg case DRM_FORMAT_YVU444: 2305b8e80941Smrg return 3; 2306b8e80941Smrg 2307848b8605Smrg default: 2308848b8605Smrg return 0; 2309848b8605Smrg } 2310b8e80941Smrg} 2311b8e80941Smrg 2312b8e80941Smrg/* Returns the total number of file descriptors. Zero indicates an error. */ 2313b8e80941Smrgstatic unsigned 2314b8e80941Smrgdri2_check_dma_buf_format(const _EGLImageAttribs *attrs) 2315b8e80941Smrg{ 2316b8e80941Smrg unsigned plane_n = dri2_num_fourcc_format_planes(attrs->DMABufFourCC.Value); 2317b8e80941Smrg if (plane_n == 0) { 2318b8e80941Smrg _eglError(EGL_BAD_MATCH, "unknown drm fourcc format"); 2319b8e80941Smrg return 0; 2320b8e80941Smrg } 2321b8e80941Smrg 2322b8e80941Smrg for (unsigned i = plane_n; i < DMA_BUF_MAX_PLANES; i++) { 2323b8e80941Smrg /** 2324b8e80941Smrg * The modifiers extension spec says: 2325b8e80941Smrg * 2326b8e80941Smrg * "Modifiers may modify any attribute of a buffer import, including 2327b8e80941Smrg * but not limited to adding extra planes to a format which 2328b8e80941Smrg * otherwise does not have those planes. As an example, a modifier 2329b8e80941Smrg * may add a plane for an external compression buffer to a 2330b8e80941Smrg * single-plane format. The exact meaning and effect of any 2331b8e80941Smrg * modifier is canonically defined by drm_fourcc.h, not as part of 2332b8e80941Smrg * this extension." 2333b8e80941Smrg */ 2334b8e80941Smrg if (attrs->DMABufPlaneModifiersLo[i].IsPresent && 2335b8e80941Smrg attrs->DMABufPlaneModifiersHi[i].IsPresent) { 2336b8e80941Smrg plane_n = i + 1; 2337b8e80941Smrg } 2338b8e80941Smrg } 2339848b8605Smrg 2340848b8605Smrg /** 2341848b8605Smrg * The spec says: 2342848b8605Smrg * 2343848b8605Smrg * "* If <target> is EGL_LINUX_DMA_BUF_EXT, and the list of attributes is 2344848b8605Smrg * incomplete, EGL_BAD_PARAMETER is generated." 2345848b8605Smrg */ 2346b8e80941Smrg for (unsigned i = 0; i < plane_n; ++i) { 2347848b8605Smrg if (!attrs->DMABufPlaneFds[i].IsPresent || 2348848b8605Smrg !attrs->DMABufPlaneOffsets[i].IsPresent || 2349848b8605Smrg !attrs->DMABufPlanePitches[i].IsPresent) { 2350848b8605Smrg _eglError(EGL_BAD_PARAMETER, "plane attribute(s) missing"); 2351848b8605Smrg return 0; 2352848b8605Smrg } 2353848b8605Smrg } 2354848b8605Smrg 2355848b8605Smrg /** 2356848b8605Smrg * The spec also says: 2357848b8605Smrg * 2358848b8605Smrg * "If <target> is EGL_LINUX_DMA_BUF_EXT, and the EGL_LINUX_DRM_FOURCC_EXT 2359848b8605Smrg * attribute indicates a single-plane format, EGL_BAD_ATTRIBUTE is 2360848b8605Smrg * generated if any of the EGL_DMA_BUF_PLANE1_* or EGL_DMA_BUF_PLANE2_* 2361b8e80941Smrg * or EGL_DMA_BUF_PLANE3_* attributes are specified." 2362848b8605Smrg */ 2363b8e80941Smrg for (unsigned i = plane_n; i < DMA_BUF_MAX_PLANES; ++i) { 2364848b8605Smrg if (attrs->DMABufPlaneFds[i].IsPresent || 2365848b8605Smrg attrs->DMABufPlaneOffsets[i].IsPresent || 2366848b8605Smrg attrs->DMABufPlanePitches[i].IsPresent) { 2367848b8605Smrg _eglError(EGL_BAD_ATTRIBUTE, "too many plane attributes"); 2368848b8605Smrg return 0; 2369848b8605Smrg } 2370848b8605Smrg } 2371848b8605Smrg 2372848b8605Smrg return plane_n; 2373848b8605Smrg} 2374848b8605Smrg 2375b8e80941Smrgstatic EGLBoolean 2376b8e80941Smrgdri2_query_dma_buf_formats(_EGLDriver *drv, _EGLDisplay *disp, 2377b8e80941Smrg EGLint max, EGLint *formats, EGLint *count) 2378b8e80941Smrg{ 2379b8e80941Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2380b8e80941Smrg if (max < 0 || (max > 0 && formats == NULL)) 2381b8e80941Smrg return _eglError(EGL_BAD_PARAMETER, "invalid value for max count of formats"); 2382b8e80941Smrg 2383b8e80941Smrg if (dri2_dpy->image->base.version < 15 || 2384b8e80941Smrg dri2_dpy->image->queryDmaBufFormats == NULL) 2385b8e80941Smrg return EGL_FALSE; 2386b8e80941Smrg 2387b8e80941Smrg if (!dri2_dpy->image->queryDmaBufFormats(dri2_dpy->dri_screen, max, 2388b8e80941Smrg formats, count)) 2389b8e80941Smrg return EGL_FALSE; 2390b8e80941Smrg 2391b8e80941Smrg if (max > 0) { 2392b8e80941Smrg /* Assert that all of the formats returned are actually fourcc formats. 2393b8e80941Smrg * Some day, if we want the internal interface function to be able to 2394b8e80941Smrg * return the fake fourcc formats defined in dri_interface.h, we'll have 2395b8e80941Smrg * to do something more clever here to pair the list down to just real 2396b8e80941Smrg * fourcc formats so that we don't leak the fake internal ones. 2397b8e80941Smrg */ 2398b8e80941Smrg for (int i = 0; i < *count; i++) { 2399b8e80941Smrg assert(dri2_num_fourcc_format_planes(formats[i]) > 0); 2400b8e80941Smrg } 2401b8e80941Smrg } 2402b8e80941Smrg 2403b8e80941Smrg return EGL_TRUE; 2404b8e80941Smrg} 2405b8e80941Smrg 2406b8e80941Smrgstatic EGLBoolean 2407b8e80941Smrgdri2_query_dma_buf_modifiers(_EGLDriver *drv, _EGLDisplay *disp, EGLint format, 2408b8e80941Smrg EGLint max, EGLuint64KHR *modifiers, 2409b8e80941Smrg EGLBoolean *external_only, EGLint *count) 2410b8e80941Smrg{ 2411b8e80941Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2412b8e80941Smrg 2413b8e80941Smrg if (dri2_num_fourcc_format_planes(format) == 0) 2414b8e80941Smrg return _eglError(EGL_BAD_PARAMETER, "invalid fourcc format"); 2415b8e80941Smrg 2416b8e80941Smrg if (max < 0) 2417b8e80941Smrg return _eglError(EGL_BAD_PARAMETER, "invalid value for max count of formats"); 2418b8e80941Smrg 2419b8e80941Smrg if (max > 0 && modifiers == NULL) 2420b8e80941Smrg return _eglError(EGL_BAD_PARAMETER, "invalid modifiers array"); 2421b8e80941Smrg 2422b8e80941Smrg if (dri2_dpy->image->base.version < 15 || 2423b8e80941Smrg dri2_dpy->image->queryDmaBufModifiers == NULL) 2424b8e80941Smrg return EGL_FALSE; 2425b8e80941Smrg 2426b8e80941Smrg if (dri2_dpy->image->queryDmaBufModifiers(dri2_dpy->dri_screen, format, 2427b8e80941Smrg max, modifiers, 2428b8e80941Smrg (unsigned int *) external_only, 2429b8e80941Smrg count) == false) 2430b8e80941Smrg return _eglError(EGL_BAD_PARAMETER, "invalid format"); 2431b8e80941Smrg 2432b8e80941Smrg return EGL_TRUE; 2433b8e80941Smrg} 2434b8e80941Smrg 2435848b8605Smrg/** 2436848b8605Smrg * The spec says: 2437848b8605Smrg * 2438848b8605Smrg * "If eglCreateImageKHR is successful for a EGL_LINUX_DMA_BUF_EXT target, the 2439848b8605Smrg * EGL will take a reference to the dma_buf(s) which it will release at any 2440848b8605Smrg * time while the EGLDisplay is initialized. It is the responsibility of the 2441848b8605Smrg * application to close the dma_buf file descriptors." 2442848b8605Smrg * 2443848b8605Smrg * Therefore we must never close or otherwise modify the file descriptors. 2444848b8605Smrg */ 2445b8e80941Smrg_EGLImage * 2446848b8605Smrgdri2_create_image_dma_buf(_EGLDisplay *disp, _EGLContext *ctx, 2447b8e80941Smrg EGLClientBuffer buffer, const EGLint *attr_list) 2448848b8605Smrg{ 2449848b8605Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2450848b8605Smrg _EGLImage *res; 2451848b8605Smrg _EGLImageAttribs attrs; 2452848b8605Smrg __DRIimage *dri_image; 2453848b8605Smrg unsigned num_fds; 2454b8e80941Smrg int fds[DMA_BUF_MAX_PLANES]; 2455b8e80941Smrg int pitches[DMA_BUF_MAX_PLANES]; 2456b8e80941Smrg int offsets[DMA_BUF_MAX_PLANES]; 2457b8e80941Smrg uint64_t modifier; 2458b8e80941Smrg bool has_modifier = false; 2459848b8605Smrg unsigned error; 2460848b8605Smrg 2461848b8605Smrg /** 2462848b8605Smrg * The spec says: 2463848b8605Smrg * 2464848b8605Smrg * ""* If <target> is EGL_LINUX_DMA_BUF_EXT and <buffer> is not NULL, the 2465848b8605Smrg * error EGL_BAD_PARAMETER is generated." 2466848b8605Smrg */ 2467848b8605Smrg if (buffer != NULL) { 2468848b8605Smrg _eglError(EGL_BAD_PARAMETER, "buffer not NULL"); 2469848b8605Smrg return NULL; 2470848b8605Smrg } 2471848b8605Smrg 2472b8e80941Smrg if (!_eglParseImageAttribList(&attrs, disp, attr_list)) 2473848b8605Smrg return NULL; 2474848b8605Smrg 2475848b8605Smrg if (!dri2_check_dma_buf_attribs(&attrs)) 2476848b8605Smrg return NULL; 2477848b8605Smrg 2478848b8605Smrg num_fds = dri2_check_dma_buf_format(&attrs); 2479848b8605Smrg if (!num_fds) 2480848b8605Smrg return NULL; 2481848b8605Smrg 2482b8e80941Smrg for (unsigned i = 0; i < num_fds; ++i) { 2483848b8605Smrg fds[i] = attrs.DMABufPlaneFds[i].Value; 2484848b8605Smrg pitches[i] = attrs.DMABufPlanePitches[i].Value; 2485848b8605Smrg offsets[i] = attrs.DMABufPlaneOffsets[i].Value; 2486848b8605Smrg } 2487848b8605Smrg 2488b8e80941Smrg /* dri2_check_dma_buf_attribs ensures that the modifier, if available, 2489b8e80941Smrg * will be present in attrs.DMABufPlaneModifiersLo[0] and 2490b8e80941Smrg * attrs.DMABufPlaneModifiersHi[0] */ 2491b8e80941Smrg if (attrs.DMABufPlaneModifiersLo[0].IsPresent) { 2492b8e80941Smrg modifier = combine_u32_into_u64(attrs.DMABufPlaneModifiersHi[0].Value, 2493b8e80941Smrg attrs.DMABufPlaneModifiersLo[0].Value); 2494b8e80941Smrg has_modifier = true; 2495b8e80941Smrg } 2496b8e80941Smrg 2497b8e80941Smrg if (has_modifier) { 2498b8e80941Smrg if (dri2_dpy->image->base.version < 15 || 2499b8e80941Smrg dri2_dpy->image->createImageFromDmaBufs2 == NULL) { 2500b8e80941Smrg _eglError(EGL_BAD_MATCH, "unsupported dma_buf format modifier"); 2501b8e80941Smrg return EGL_NO_IMAGE_KHR; 2502b8e80941Smrg } 2503b8e80941Smrg dri_image = 2504b8e80941Smrg dri2_dpy->image->createImageFromDmaBufs2(dri2_dpy->dri_screen, 2505b8e80941Smrg attrs.Width, attrs.Height, attrs.DMABufFourCC.Value, 2506b8e80941Smrg modifier, fds, num_fds, pitches, offsets, 2507b8e80941Smrg attrs.DMABufYuvColorSpaceHint.Value, 2508b8e80941Smrg attrs.DMABufSampleRangeHint.Value, 2509b8e80941Smrg attrs.DMABufChromaHorizontalSiting.Value, 2510b8e80941Smrg attrs.DMABufChromaVerticalSiting.Value, 2511b8e80941Smrg &error, 2512b8e80941Smrg NULL); 2513b8e80941Smrg } 2514b8e80941Smrg else { 2515b8e80941Smrg dri_image = 2516b8e80941Smrg dri2_dpy->image->createImageFromDmaBufs(dri2_dpy->dri_screen, 2517b8e80941Smrg attrs.Width, attrs.Height, attrs.DMABufFourCC.Value, 2518b8e80941Smrg fds, num_fds, pitches, offsets, 2519b8e80941Smrg attrs.DMABufYuvColorSpaceHint.Value, 2520b8e80941Smrg attrs.DMABufSampleRangeHint.Value, 2521b8e80941Smrg attrs.DMABufChromaHorizontalSiting.Value, 2522b8e80941Smrg attrs.DMABufChromaVerticalSiting.Value, 2523b8e80941Smrg &error, 2524b8e80941Smrg NULL); 2525b8e80941Smrg } 2526848b8605Smrg dri2_create_image_khr_texture_error(error); 2527848b8605Smrg 2528848b8605Smrg if (!dri_image) 2529848b8605Smrg return EGL_NO_IMAGE_KHR; 2530848b8605Smrg 2531848b8605Smrg res = dri2_create_image_from_dri(disp, dri_image); 2532848b8605Smrg 2533848b8605Smrg return res; 2534848b8605Smrg} 2535848b8605Smrgstatic _EGLImage * 2536848b8605Smrgdri2_create_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp, 2537b8e80941Smrg const EGLint *attr_list) 2538848b8605Smrg{ 2539848b8605Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2540848b8605Smrg struct dri2_egl_image *dri2_img; 2541848b8605Smrg _EGLImageAttribs attrs; 2542848b8605Smrg unsigned int dri_use, valid_mask; 2543848b8605Smrg int format; 2544848b8605Smrg 2545848b8605Smrg (void) drv; 2546848b8605Smrg 2547848b8605Smrg if (!attr_list) { 2548b8e80941Smrg _eglError(EGL_BAD_PARAMETER, __func__); 2549b8e80941Smrg return EGL_NO_IMAGE_KHR; 2550848b8605Smrg } 2551848b8605Smrg 2552b8e80941Smrg if (!_eglParseImageAttribList(&attrs, disp, attr_list)) 2553b8e80941Smrg return EGL_NO_IMAGE_KHR; 2554848b8605Smrg 2555848b8605Smrg if (attrs.Width <= 0 || attrs.Height <= 0) { 2556b8e80941Smrg _eglError(EGL_BAD_PARAMETER, __func__); 2557b8e80941Smrg return EGL_NO_IMAGE_KHR; 2558848b8605Smrg } 2559848b8605Smrg 2560848b8605Smrg switch (attrs.DRMBufferFormatMESA) { 2561848b8605Smrg case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA: 2562848b8605Smrg format = __DRI_IMAGE_FORMAT_ARGB8888; 2563848b8605Smrg break; 2564848b8605Smrg default: 2565b8e80941Smrg _eglError(EGL_BAD_PARAMETER, __func__); 2566b8e80941Smrg return EGL_NO_IMAGE_KHR; 2567848b8605Smrg } 2568848b8605Smrg 2569848b8605Smrg valid_mask = 2570848b8605Smrg EGL_DRM_BUFFER_USE_SCANOUT_MESA | 2571848b8605Smrg EGL_DRM_BUFFER_USE_SHARE_MESA | 2572848b8605Smrg EGL_DRM_BUFFER_USE_CURSOR_MESA; 2573848b8605Smrg if (attrs.DRMBufferUseMESA & ~valid_mask) { 2574b8e80941Smrg _eglError(EGL_BAD_PARAMETER, __func__); 2575b8e80941Smrg return EGL_NO_IMAGE_KHR; 2576848b8605Smrg } 2577848b8605Smrg 2578848b8605Smrg dri_use = 0; 2579848b8605Smrg if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SHARE_MESA) 2580848b8605Smrg dri_use |= __DRI_IMAGE_USE_SHARE; 2581848b8605Smrg if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SCANOUT_MESA) 2582848b8605Smrg dri_use |= __DRI_IMAGE_USE_SCANOUT; 2583848b8605Smrg if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_CURSOR_MESA) 2584848b8605Smrg dri_use |= __DRI_IMAGE_USE_CURSOR; 2585848b8605Smrg 2586b8e80941Smrg dri2_img = malloc(sizeof *dri2_img); 2587b8e80941Smrg if (!dri2_img) { 2588b8e80941Smrg _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr"); 2589b8e80941Smrg return EGL_NO_IMAGE_KHR; 2590b8e80941Smrg } 2591b8e80941Smrg 2592b8e80941Smrg _eglInitImage(&dri2_img->base, disp); 2593b8e80941Smrg 2594b8e80941Smrg dri2_img->dri_image = 2595848b8605Smrg dri2_dpy->image->createImage(dri2_dpy->dri_screen, 2596b8e80941Smrg attrs.Width, attrs.Height, 2597848b8605Smrg format, dri_use, dri2_img); 2598848b8605Smrg if (dri2_img->dri_image == NULL) { 2599b8e80941Smrg free(dri2_img); 2600b8e80941Smrg _eglError(EGL_BAD_ALLOC, "dri2_create_drm_image_mesa"); 2601b8e80941Smrg return EGL_NO_IMAGE_KHR; 2602848b8605Smrg } 2603848b8605Smrg 2604848b8605Smrg return &dri2_img->base; 2605848b8605Smrg} 2606848b8605Smrg 2607848b8605Smrgstatic EGLBoolean 2608848b8605Smrgdri2_export_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *img, 2609b8e80941Smrg EGLint *name, EGLint *handle, EGLint *stride) 2610848b8605Smrg{ 2611848b8605Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2612848b8605Smrg struct dri2_egl_image *dri2_img = dri2_egl_image(img); 2613848b8605Smrg 2614848b8605Smrg (void) drv; 2615848b8605Smrg 2616848b8605Smrg if (name && !dri2_dpy->image->queryImage(dri2_img->dri_image, 2617b8e80941Smrg __DRI_IMAGE_ATTRIB_NAME, name)) 2618b8e80941Smrg return _eglError(EGL_BAD_ALLOC, "dri2_export_drm_image_mesa"); 2619848b8605Smrg 2620848b8605Smrg if (handle) 2621848b8605Smrg dri2_dpy->image->queryImage(dri2_img->dri_image, 2622b8e80941Smrg __DRI_IMAGE_ATTRIB_HANDLE, handle); 2623848b8605Smrg 2624848b8605Smrg if (stride) 2625848b8605Smrg dri2_dpy->image->queryImage(dri2_img->dri_image, 2626b8e80941Smrg __DRI_IMAGE_ATTRIB_STRIDE, stride); 2627848b8605Smrg 2628848b8605Smrg return EGL_TRUE; 2629848b8605Smrg} 2630b8e80941Smrg 2631b8e80941Smrg/** 2632b8e80941Smrg * Checks if we can support EGL_MESA_image_dma_buf_export on this image. 2633b8e80941Smrg 2634b8e80941Smrg * The spec provides a boolean return for the driver to reject exporting for 2635b8e80941Smrg * basically any reason, but doesn't specify any particular error cases. For 2636b8e80941Smrg * now, we just fail if we don't have a DRM fourcc for the format. 2637b8e80941Smrg */ 2638b8e80941Smrgstatic bool 2639b8e80941Smrgdri2_can_export_dma_buf_image(_EGLDisplay *disp, _EGLImage *img) 2640b8e80941Smrg{ 2641b8e80941Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2642b8e80941Smrg struct dri2_egl_image *dri2_img = dri2_egl_image(img); 2643b8e80941Smrg EGLint fourcc; 2644b8e80941Smrg 2645b8e80941Smrg if (!dri2_dpy->image->queryImage(dri2_img->dri_image, 2646b8e80941Smrg __DRI_IMAGE_ATTRIB_FOURCC, &fourcc)) { 2647b8e80941Smrg return false; 2648b8e80941Smrg } 2649b8e80941Smrg 2650b8e80941Smrg return true; 2651b8e80941Smrg} 2652b8e80941Smrg 2653b8e80941Smrgstatic EGLBoolean 2654b8e80941Smrgdri2_export_dma_buf_image_query_mesa(_EGLDriver *drv, _EGLDisplay *disp, 2655b8e80941Smrg _EGLImage *img, 2656b8e80941Smrg EGLint *fourcc, EGLint *nplanes, 2657b8e80941Smrg EGLuint64KHR *modifiers) 2658b8e80941Smrg{ 2659b8e80941Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2660b8e80941Smrg struct dri2_egl_image *dri2_img = dri2_egl_image(img); 2661b8e80941Smrg int num_planes; 2662b8e80941Smrg 2663b8e80941Smrg (void) drv; 2664b8e80941Smrg 2665b8e80941Smrg if (!dri2_can_export_dma_buf_image(disp, img)) 2666b8e80941Smrg return EGL_FALSE; 2667b8e80941Smrg 2668b8e80941Smrg dri2_dpy->image->queryImage(dri2_img->dri_image, 2669b8e80941Smrg __DRI_IMAGE_ATTRIB_NUM_PLANES, &num_planes); 2670b8e80941Smrg if (nplanes) 2671b8e80941Smrg *nplanes = num_planes; 2672b8e80941Smrg 2673b8e80941Smrg if (fourcc) 2674b8e80941Smrg dri2_dpy->image->queryImage(dri2_img->dri_image, 2675b8e80941Smrg __DRI_IMAGE_ATTRIB_FOURCC, fourcc); 2676b8e80941Smrg 2677b8e80941Smrg if (modifiers) { 2678b8e80941Smrg int mod_hi, mod_lo; 2679b8e80941Smrg uint64_t modifier = DRM_FORMAT_MOD_INVALID; 2680b8e80941Smrg bool query; 2681b8e80941Smrg 2682b8e80941Smrg query = dri2_dpy->image->queryImage(dri2_img->dri_image, 2683b8e80941Smrg __DRI_IMAGE_ATTRIB_MODIFIER_UPPER, 2684b8e80941Smrg &mod_hi); 2685b8e80941Smrg query &= dri2_dpy->image->queryImage(dri2_img->dri_image, 2686b8e80941Smrg __DRI_IMAGE_ATTRIB_MODIFIER_LOWER, 2687b8e80941Smrg &mod_lo); 2688b8e80941Smrg if (query) 2689b8e80941Smrg modifier = combine_u32_into_u64 (mod_hi, mod_lo); 2690b8e80941Smrg 2691b8e80941Smrg for (int i = 0; i < num_planes; i++) 2692b8e80941Smrg modifiers[i] = modifier; 2693b8e80941Smrg } 2694b8e80941Smrg 2695b8e80941Smrg return EGL_TRUE; 2696b8e80941Smrg} 2697b8e80941Smrg 2698b8e80941Smrgstatic EGLBoolean 2699b8e80941Smrgdri2_export_dma_buf_image_mesa(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *img, 2700b8e80941Smrg int *fds, EGLint *strides, EGLint *offsets) 2701b8e80941Smrg{ 2702b8e80941Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2703b8e80941Smrg struct dri2_egl_image *dri2_img = dri2_egl_image(img); 2704b8e80941Smrg EGLint nplanes; 2705b8e80941Smrg 2706b8e80941Smrg (void) drv; 2707b8e80941Smrg 2708b8e80941Smrg if (!dri2_can_export_dma_buf_image(disp, img)) 2709b8e80941Smrg return EGL_FALSE; 2710b8e80941Smrg 2711b8e80941Smrg /* EGL_MESA_image_dma_buf_export spec says: 2712b8e80941Smrg * "If the number of fds is less than the number of planes, then 2713b8e80941Smrg * subsequent fd slots should contain -1." 2714b8e80941Smrg */ 2715b8e80941Smrg if (fds) { 2716b8e80941Smrg /* Query nplanes so that we know how big the given array is. */ 2717b8e80941Smrg dri2_dpy->image->queryImage(dri2_img->dri_image, 2718b8e80941Smrg __DRI_IMAGE_ATTRIB_NUM_PLANES, &nplanes); 2719b8e80941Smrg memset(fds, -1, nplanes * sizeof(int)); 2720b8e80941Smrg } 2721b8e80941Smrg 2722b8e80941Smrg /* rework later to provide multiple fds/strides/offsets */ 2723b8e80941Smrg if (fds) 2724b8e80941Smrg dri2_dpy->image->queryImage(dri2_img->dri_image, 2725b8e80941Smrg __DRI_IMAGE_ATTRIB_FD, fds); 2726b8e80941Smrg 2727b8e80941Smrg if (strides) 2728b8e80941Smrg dri2_dpy->image->queryImage(dri2_img->dri_image, 2729b8e80941Smrg __DRI_IMAGE_ATTRIB_STRIDE, strides); 2730b8e80941Smrg 2731b8e80941Smrg if (offsets) { 2732b8e80941Smrg int img_offset; 2733b8e80941Smrg bool ret = dri2_dpy->image->queryImage(dri2_img->dri_image, 2734b8e80941Smrg __DRI_IMAGE_ATTRIB_OFFSET, &img_offset); 2735b8e80941Smrg if (ret) 2736b8e80941Smrg offsets[0] = img_offset; 2737b8e80941Smrg else 2738b8e80941Smrg offsets[0] = 0; 2739b8e80941Smrg } 2740b8e80941Smrg 2741b8e80941Smrg return EGL_TRUE; 2742b8e80941Smrg} 2743b8e80941Smrg 2744848b8605Smrg#endif 2745848b8605Smrg 2746b8e80941Smrg_EGLImage * 2747b8e80941Smrgdri2_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp, 2748b8e80941Smrg _EGLContext *ctx, EGLenum target, 2749b8e80941Smrg EGLClientBuffer buffer, const EGLint *attr_list) 2750b8e80941Smrg{ 2751b8e80941Smrg (void) drv; 2752b8e80941Smrg 2753b8e80941Smrg switch (target) { 2754b8e80941Smrg case EGL_GL_TEXTURE_2D_KHR: 2755b8e80941Smrg case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR: 2756b8e80941Smrg case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR: 2757b8e80941Smrg case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR: 2758b8e80941Smrg case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR: 2759b8e80941Smrg case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR: 2760b8e80941Smrg case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR: 2761b8e80941Smrg case EGL_GL_TEXTURE_3D_KHR: 2762b8e80941Smrg return dri2_create_image_khr_texture(disp, ctx, target, buffer, attr_list); 2763b8e80941Smrg case EGL_GL_RENDERBUFFER_KHR: 2764b8e80941Smrg return dri2_create_image_khr_renderbuffer(disp, ctx, buffer, attr_list); 2765b8e80941Smrg#ifdef HAVE_LIBDRM 2766b8e80941Smrg case EGL_DRM_BUFFER_MESA: 2767b8e80941Smrg return dri2_create_image_mesa_drm_buffer(disp, ctx, buffer, attr_list); 2768b8e80941Smrg case EGL_LINUX_DMA_BUF_EXT: 2769b8e80941Smrg return dri2_create_image_dma_buf(disp, ctx, buffer, attr_list); 2770b8e80941Smrg#endif 2771b8e80941Smrg#ifdef HAVE_WAYLAND_PLATFORM 2772b8e80941Smrg case EGL_WAYLAND_BUFFER_WL: 2773b8e80941Smrg return dri2_create_image_wayland_wl_buffer(disp, ctx, buffer, attr_list); 2774b8e80941Smrg#endif 2775b8e80941Smrg default: 2776b8e80941Smrg _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr"); 2777b8e80941Smrg return EGL_NO_IMAGE_KHR; 2778b8e80941Smrg } 2779b8e80941Smrg} 2780b8e80941Smrg 2781b8e80941Smrgstatic EGLBoolean 2782b8e80941Smrgdri2_destroy_image_khr(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *image) 2783b8e80941Smrg{ 2784b8e80941Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2785b8e80941Smrg struct dri2_egl_image *dri2_img = dri2_egl_image(image); 2786b8e80941Smrg 2787b8e80941Smrg (void) drv; 2788b8e80941Smrg 2789b8e80941Smrg dri2_dpy->image->destroyImage(dri2_img->dri_image); 2790b8e80941Smrg free(dri2_img); 2791b8e80941Smrg 2792b8e80941Smrg return EGL_TRUE; 2793b8e80941Smrg} 2794b8e80941Smrg 2795848b8605Smrg#ifdef HAVE_WAYLAND_PLATFORM 2796848b8605Smrg 2797848b8605Smrgstatic void 2798848b8605Smrgdri2_wl_reference_buffer(void *user_data, uint32_t name, int fd, 2799848b8605Smrg struct wl_drm_buffer *buffer) 2800848b8605Smrg{ 2801848b8605Smrg _EGLDisplay *disp = user_data; 2802848b8605Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2803848b8605Smrg __DRIimage *img; 2804b8e80941Smrg int dri_components = 0; 2805848b8605Smrg 2806848b8605Smrg if (fd == -1) 2807848b8605Smrg img = dri2_dpy->image->createImageFromNames(dri2_dpy->dri_screen, 2808848b8605Smrg buffer->width, 2809848b8605Smrg buffer->height, 2810848b8605Smrg buffer->format, 2811848b8605Smrg (int*)&name, 1, 2812848b8605Smrg buffer->stride, 2813848b8605Smrg buffer->offset, 2814848b8605Smrg NULL); 2815848b8605Smrg else 2816848b8605Smrg img = dri2_dpy->image->createImageFromFds(dri2_dpy->dri_screen, 2817848b8605Smrg buffer->width, 2818848b8605Smrg buffer->height, 2819848b8605Smrg buffer->format, 2820848b8605Smrg &fd, 1, 2821848b8605Smrg buffer->stride, 2822848b8605Smrg buffer->offset, 2823848b8605Smrg NULL); 2824848b8605Smrg 2825848b8605Smrg if (img == NULL) 2826848b8605Smrg return; 2827848b8605Smrg 2828848b8605Smrg dri2_dpy->image->queryImage(img, __DRI_IMAGE_ATTRIB_COMPONENTS, &dri_components); 2829848b8605Smrg 2830848b8605Smrg buffer->driver_format = NULL; 2831b8e80941Smrg for (int i = 0; i < ARRAY_SIZE(wl_drm_components); i++) 2832848b8605Smrg if (wl_drm_components[i].dri_components == dri_components) 2833848b8605Smrg buffer->driver_format = &wl_drm_components[i]; 2834848b8605Smrg 2835848b8605Smrg if (buffer->driver_format == NULL) 2836848b8605Smrg dri2_dpy->image->destroyImage(img); 2837848b8605Smrg else 2838848b8605Smrg buffer->driver_buffer = img; 2839848b8605Smrg} 2840848b8605Smrg 2841848b8605Smrgstatic void 2842848b8605Smrgdri2_wl_release_buffer(void *user_data, struct wl_drm_buffer *buffer) 2843848b8605Smrg{ 2844848b8605Smrg _EGLDisplay *disp = user_data; 2845848b8605Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2846848b8605Smrg 2847848b8605Smrg dri2_dpy->image->destroyImage(buffer->driver_buffer); 2848848b8605Smrg} 2849848b8605Smrg 2850848b8605Smrgstatic EGLBoolean 2851848b8605Smrgdri2_bind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *disp, 2852b8e80941Smrg struct wl_display *wl_dpy) 2853848b8605Smrg{ 2854848b8605Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2855b8e80941Smrg const struct wayland_drm_callbacks wl_drm_callbacks = { 2856b8e80941Smrg .authenticate = (int(*)(void *, uint32_t)) dri2_dpy->vtbl->authenticate, 2857b8e80941Smrg .reference_buffer = dri2_wl_reference_buffer, 2858b8e80941Smrg .release_buffer = dri2_wl_release_buffer, 2859b8e80941Smrg .is_format_supported = dri2_wl_is_format_supported 2860b8e80941Smrg }; 2861848b8605Smrg int flags = 0; 2862848b8605Smrg uint64_t cap; 2863848b8605Smrg 2864848b8605Smrg (void) drv; 2865848b8605Smrg 2866848b8605Smrg if (dri2_dpy->wl_server_drm) 2867b8e80941Smrg return EGL_FALSE; 2868848b8605Smrg 2869848b8605Smrg if (drmGetCap(dri2_dpy->fd, DRM_CAP_PRIME, &cap) == 0 && 2870848b8605Smrg cap == (DRM_PRIME_CAP_IMPORT | DRM_PRIME_CAP_EXPORT) && 2871848b8605Smrg dri2_dpy->image->base.version >= 7 && 2872848b8605Smrg dri2_dpy->image->createImageFromFds != NULL) 2873848b8605Smrg flags |= WAYLAND_DRM_PRIME; 2874848b8605Smrg 2875848b8605Smrg dri2_dpy->wl_server_drm = 2876b8e80941Smrg wayland_drm_init(wl_dpy, dri2_dpy->device_name, 2877848b8605Smrg &wl_drm_callbacks, disp, flags); 2878848b8605Smrg 2879848b8605Smrg if (!dri2_dpy->wl_server_drm) 2880b8e80941Smrg return EGL_FALSE; 2881848b8605Smrg 2882848b8605Smrg#ifdef HAVE_DRM_PLATFORM 2883848b8605Smrg /* We have to share the wl_drm instance with gbm, so gbm can convert 2884848b8605Smrg * wl_buffers to gbm bos. */ 2885848b8605Smrg if (dri2_dpy->gbm_dri) 2886848b8605Smrg dri2_dpy->gbm_dri->wl_drm = dri2_dpy->wl_server_drm; 2887848b8605Smrg#endif 2888848b8605Smrg 2889848b8605Smrg return EGL_TRUE; 2890848b8605Smrg} 2891848b8605Smrg 2892848b8605Smrgstatic EGLBoolean 2893848b8605Smrgdri2_unbind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *disp, 2894b8e80941Smrg struct wl_display *wl_dpy) 2895848b8605Smrg{ 2896848b8605Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2897848b8605Smrg 2898848b8605Smrg (void) drv; 2899848b8605Smrg 2900848b8605Smrg if (!dri2_dpy->wl_server_drm) 2901b8e80941Smrg return EGL_FALSE; 2902848b8605Smrg 2903848b8605Smrg wayland_drm_uninit(dri2_dpy->wl_server_drm); 2904848b8605Smrg dri2_dpy->wl_server_drm = NULL; 2905848b8605Smrg 2906848b8605Smrg return EGL_TRUE; 2907848b8605Smrg} 2908848b8605Smrg 2909848b8605Smrgstatic EGLBoolean 2910848b8605Smrgdri2_query_wayland_buffer_wl(_EGLDriver *drv, _EGLDisplay *disp, 2911848b8605Smrg struct wl_resource *buffer_resource, 2912848b8605Smrg EGLint attribute, EGLint *value) 2913848b8605Smrg{ 2914848b8605Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2915848b8605Smrg struct wl_drm_buffer *buffer; 2916848b8605Smrg const struct wl_drm_components_descriptor *format; 2917848b8605Smrg 2918848b8605Smrg buffer = wayland_drm_buffer_get(dri2_dpy->wl_server_drm, buffer_resource); 2919848b8605Smrg if (!buffer) 2920848b8605Smrg return EGL_FALSE; 2921848b8605Smrg 2922848b8605Smrg format = buffer->driver_format; 2923848b8605Smrg switch (attribute) { 2924848b8605Smrg case EGL_TEXTURE_FORMAT: 2925848b8605Smrg *value = format->components; 2926848b8605Smrg return EGL_TRUE; 2927848b8605Smrg case EGL_WIDTH: 2928848b8605Smrg *value = buffer->width; 2929848b8605Smrg return EGL_TRUE; 2930848b8605Smrg case EGL_HEIGHT: 2931848b8605Smrg *value = buffer->height; 2932848b8605Smrg return EGL_TRUE; 2933848b8605Smrg } 2934848b8605Smrg 2935848b8605Smrg return EGL_FALSE; 2936848b8605Smrg} 2937848b8605Smrg#endif 2938848b8605Smrg 2939848b8605Smrgstatic void 2940b8e80941Smrgdri2_egl_ref_sync(struct dri2_egl_sync *sync) 2941848b8605Smrg{ 2942b8e80941Smrg p_atomic_inc(&sync->refcount); 2943b8e80941Smrg} 2944b8e80941Smrg 2945b8e80941Smrgstatic void 2946b8e80941Smrgdri2_egl_unref_sync(struct dri2_egl_display *dri2_dpy, 2947b8e80941Smrg struct dri2_egl_sync *dri2_sync) 2948b8e80941Smrg{ 2949b8e80941Smrg if (p_atomic_dec_zero(&dri2_sync->refcount)) { 2950b8e80941Smrg switch (dri2_sync->base.Type) { 2951b8e80941Smrg case EGL_SYNC_REUSABLE_KHR: 2952b8e80941Smrg cnd_destroy(&dri2_sync->cond); 2953b8e80941Smrg break; 2954b8e80941Smrg case EGL_SYNC_NATIVE_FENCE_ANDROID: 2955b8e80941Smrg if (dri2_sync->base.SyncFd != EGL_NO_NATIVE_FENCE_FD_ANDROID) 2956b8e80941Smrg close(dri2_sync->base.SyncFd); 2957b8e80941Smrg break; 2958b8e80941Smrg default: 2959b8e80941Smrg break; 2960b8e80941Smrg } 2961b8e80941Smrg 2962b8e80941Smrg if (dri2_sync->fence) 2963b8e80941Smrg dri2_dpy->fence->destroy_fence(dri2_dpy->dri_screen, dri2_sync->fence); 2964b8e80941Smrg 2965b8e80941Smrg free(dri2_sync); 2966b8e80941Smrg } 2967b8e80941Smrg} 2968b8e80941Smrg 2969b8e80941Smrgstatic _EGLSync * 2970b8e80941Smrgdri2_create_sync(_EGLDriver *drv, _EGLDisplay *disp, 2971b8e80941Smrg EGLenum type, const EGLAttrib *attrib_list) 2972b8e80941Smrg{ 2973b8e80941Smrg _EGLContext *ctx = _eglGetCurrentContext(); 2974b8e80941Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2975b8e80941Smrg struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); 2976b8e80941Smrg struct dri2_egl_sync *dri2_sync; 2977b8e80941Smrg EGLint ret; 2978b8e80941Smrg pthread_condattr_t attr; 2979b8e80941Smrg 2980b8e80941Smrg dri2_sync = calloc(1, sizeof(struct dri2_egl_sync)); 2981b8e80941Smrg if (!dri2_sync) { 2982b8e80941Smrg _eglError(EGL_BAD_ALLOC, "eglCreateSyncKHR"); 2983b8e80941Smrg return NULL; 2984b8e80941Smrg } 2985b8e80941Smrg 2986b8e80941Smrg if (!_eglInitSync(&dri2_sync->base, disp, type, attrib_list)) { 2987b8e80941Smrg free(dri2_sync); 2988b8e80941Smrg return NULL; 2989b8e80941Smrg } 2990b8e80941Smrg 2991b8e80941Smrg switch (type) { 2992b8e80941Smrg case EGL_SYNC_FENCE_KHR: 2993b8e80941Smrg dri2_sync->fence = dri2_dpy->fence->create_fence(dri2_ctx->dri_context); 2994b8e80941Smrg if (!dri2_sync->fence) { 2995b8e80941Smrg /* Why did it fail? DRI doesn't return an error code, so we emit 2996b8e80941Smrg * a generic EGL error that doesn't communicate user error. 2997b8e80941Smrg */ 2998b8e80941Smrg _eglError(EGL_BAD_ALLOC, "eglCreateSyncKHR"); 2999b8e80941Smrg free(dri2_sync); 3000b8e80941Smrg return NULL; 3001b8e80941Smrg } 3002b8e80941Smrg break; 3003b8e80941Smrg 3004b8e80941Smrg case EGL_SYNC_CL_EVENT_KHR: 3005b8e80941Smrg dri2_sync->fence = dri2_dpy->fence->get_fence_from_cl_event( 3006b8e80941Smrg dri2_dpy->dri_screen, 3007b8e80941Smrg dri2_sync->base.CLEvent); 3008b8e80941Smrg /* this can only happen if the cl_event passed in is invalid. */ 3009b8e80941Smrg if (!dri2_sync->fence) { 3010b8e80941Smrg _eglError(EGL_BAD_ATTRIBUTE, "eglCreateSyncKHR"); 3011b8e80941Smrg free(dri2_sync); 3012b8e80941Smrg return NULL; 3013b8e80941Smrg } 3014b8e80941Smrg 3015b8e80941Smrg /* the initial status must be "signaled" if the cl_event is signaled */ 3016b8e80941Smrg if (dri2_dpy->fence->client_wait_sync(dri2_ctx->dri_context, 3017b8e80941Smrg dri2_sync->fence, 0, 0)) 3018b8e80941Smrg dri2_sync->base.SyncStatus = EGL_SIGNALED_KHR; 3019b8e80941Smrg break; 3020b8e80941Smrg 3021b8e80941Smrg case EGL_SYNC_REUSABLE_KHR: 3022b8e80941Smrg /* intialize attr */ 3023b8e80941Smrg ret = pthread_condattr_init(&attr); 3024b8e80941Smrg 3025b8e80941Smrg if (ret) { 3026b8e80941Smrg _eglError(EGL_BAD_ACCESS, "eglCreateSyncKHR"); 3027b8e80941Smrg free(dri2_sync); 3028b8e80941Smrg return NULL; 3029b8e80941Smrg } 3030b8e80941Smrg 3031b8e80941Smrg /* change clock attribute to CLOCK_MONOTONIC */ 3032b8e80941Smrg ret = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC); 3033b8e80941Smrg 3034b8e80941Smrg if (ret) { 3035b8e80941Smrg _eglError(EGL_BAD_ACCESS, "eglCreateSyncKHR"); 3036b8e80941Smrg free(dri2_sync); 3037b8e80941Smrg return NULL; 3038b8e80941Smrg } 3039b8e80941Smrg 3040b8e80941Smrg ret = pthread_cond_init(&dri2_sync->cond, &attr); 3041b8e80941Smrg 3042b8e80941Smrg if (ret) { 3043b8e80941Smrg _eglError(EGL_BAD_ACCESS, "eglCreateSyncKHR"); 3044b8e80941Smrg free(dri2_sync); 3045b8e80941Smrg return NULL; 3046b8e80941Smrg } 3047b8e80941Smrg 3048b8e80941Smrg /* initial status of reusable sync must be "unsignaled" */ 3049b8e80941Smrg dri2_sync->base.SyncStatus = EGL_UNSIGNALED_KHR; 3050b8e80941Smrg break; 3051848b8605Smrg 3052b8e80941Smrg case EGL_SYNC_NATIVE_FENCE_ANDROID: 3053b8e80941Smrg if (dri2_dpy->fence->create_fence_fd) { 3054b8e80941Smrg dri2_sync->fence = dri2_dpy->fence->create_fence_fd( 3055b8e80941Smrg dri2_ctx->dri_context, 3056b8e80941Smrg dri2_sync->base.SyncFd); 3057b8e80941Smrg } 3058b8e80941Smrg if (!dri2_sync->fence) { 3059b8e80941Smrg _eglError(EGL_BAD_ATTRIBUTE, "eglCreateSyncKHR"); 3060b8e80941Smrg free(dri2_sync); 3061b8e80941Smrg return NULL; 3062b8e80941Smrg } 3063b8e80941Smrg break; 3064b8e80941Smrg } 3065b8e80941Smrg 3066b8e80941Smrg p_atomic_set(&dri2_sync->refcount, 1); 3067b8e80941Smrg return &dri2_sync->base; 3068848b8605Smrg} 3069848b8605Smrg 3070848b8605Smrgstatic EGLBoolean 3071b8e80941Smrgdri2_destroy_sync(_EGLDriver *drv, _EGLDisplay *disp, _EGLSync *sync) 3072b8e80941Smrg{ 3073b8e80941Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 3074b8e80941Smrg struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync); 3075b8e80941Smrg EGLint ret = EGL_TRUE; 3076b8e80941Smrg EGLint err; 3077b8e80941Smrg 3078b8e80941Smrg /* if type of sync is EGL_SYNC_REUSABLE_KHR and it is not signaled yet, 3079b8e80941Smrg * then unlock all threads possibly blocked by the reusable sync before 3080b8e80941Smrg * destroying it. 3081848b8605Smrg */ 3082b8e80941Smrg if (dri2_sync->base.Type == EGL_SYNC_REUSABLE_KHR && 3083b8e80941Smrg dri2_sync->base.SyncStatus == EGL_UNSIGNALED_KHR) { 3084b8e80941Smrg dri2_sync->base.SyncStatus = EGL_SIGNALED_KHR; 3085b8e80941Smrg /* unblock all threads currently blocked by sync */ 3086b8e80941Smrg err = cnd_broadcast(&dri2_sync->cond); 3087b8e80941Smrg 3088b8e80941Smrg if (err) { 3089b8e80941Smrg _eglError(EGL_BAD_ACCESS, "eglDestroySyncKHR"); 3090b8e80941Smrg ret = EGL_FALSE; 3091848b8605Smrg } 3092848b8605Smrg } 3093848b8605Smrg 3094b8e80941Smrg dri2_egl_unref_sync(dri2_dpy, dri2_sync); 3095b8e80941Smrg 3096b8e80941Smrg return ret; 3097b8e80941Smrg} 3098b8e80941Smrg 3099b8e80941Smrgstatic EGLint 3100b8e80941Smrgdri2_dup_native_fence_fd(_EGLDriver *drv, _EGLDisplay *disp, _EGLSync *sync) 3101b8e80941Smrg{ 3102b8e80941Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 3103b8e80941Smrg struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync); 3104b8e80941Smrg 3105b8e80941Smrg assert(sync->Type == EGL_SYNC_NATIVE_FENCE_ANDROID); 3106b8e80941Smrg 3107b8e80941Smrg if (sync->SyncFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) { 3108b8e80941Smrg /* try to retrieve the actual native fence fd.. if rendering is 3109b8e80941Smrg * not flushed this will just return -1, aka NO_NATIVE_FENCE_FD: 3110b8e80941Smrg */ 3111b8e80941Smrg sync->SyncFd = dri2_dpy->fence->get_fence_fd(dri2_dpy->dri_screen, 3112b8e80941Smrg dri2_sync->fence); 3113848b8605Smrg } 3114848b8605Smrg 3115b8e80941Smrg if (sync->SyncFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) { 3116b8e80941Smrg /* if native fence fd still not created, return an error: */ 3117b8e80941Smrg _eglError(EGL_BAD_PARAMETER, "eglDupNativeFenceFDANDROID"); 3118b8e80941Smrg return EGL_NO_NATIVE_FENCE_FD_ANDROID; 3119b8e80941Smrg } 3120848b8605Smrg 3121b8e80941Smrg return dup(sync->SyncFd); 3122b8e80941Smrg} 3123848b8605Smrg 3124b8e80941Smrgstatic void 3125b8e80941Smrgdri2_set_blob_cache_funcs(_EGLDriver *drv, _EGLDisplay *disp, 3126b8e80941Smrg EGLSetBlobFuncANDROID set, 3127b8e80941Smrg EGLGetBlobFuncANDROID get) 3128b8e80941Smrg{ 3129b8e80941Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 3130b8e80941Smrg dri2_dpy->blob->set_cache_funcs(dri2_dpy->dri_screen, 3131b8e80941Smrg disp->BlobCacheSet, 3132b8e80941Smrg disp->BlobCacheGet); 3133848b8605Smrg} 3134848b8605Smrg 3135b8e80941Smrgstatic EGLint 3136b8e80941Smrgdri2_client_wait_sync(_EGLDriver *drv, _EGLDisplay *disp, _EGLSync *sync, 3137b8e80941Smrg EGLint flags, EGLTime timeout) 3138848b8605Smrg{ 3139b8e80941Smrg _EGLContext *ctx = _eglGetCurrentContext(); 3140b8e80941Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 3141b8e80941Smrg struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); 3142b8e80941Smrg struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync); 3143b8e80941Smrg unsigned wait_flags = 0; 3144848b8605Smrg 3145b8e80941Smrg EGLint ret = EGL_CONDITION_SATISFIED_KHR; 3146848b8605Smrg 3147b8e80941Smrg /* The EGL_KHR_fence_sync spec states: 3148b8e80941Smrg * 3149b8e80941Smrg * "If no context is current for the bound API, 3150b8e80941Smrg * the EGL_SYNC_FLUSH_COMMANDS_BIT_KHR bit is ignored. 3151b8e80941Smrg */ 3152b8e80941Smrg if (dri2_ctx && flags & EGL_SYNC_FLUSH_COMMANDS_BIT_KHR) 3153b8e80941Smrg wait_flags |= __DRI2_FENCE_FLAG_FLUSH_COMMANDS; 3154b8e80941Smrg 3155b8e80941Smrg /* the sync object should take a reference while waiting */ 3156b8e80941Smrg dri2_egl_ref_sync(dri2_sync); 3157b8e80941Smrg 3158b8e80941Smrg switch (sync->Type) { 3159b8e80941Smrg case EGL_SYNC_FENCE_KHR: 3160b8e80941Smrg case EGL_SYNC_NATIVE_FENCE_ANDROID: 3161b8e80941Smrg case EGL_SYNC_CL_EVENT_KHR: 3162b8e80941Smrg if (dri2_dpy->fence->client_wait_sync(dri2_ctx ? dri2_ctx->dri_context : NULL, 3163b8e80941Smrg dri2_sync->fence, wait_flags, 3164b8e80941Smrg timeout)) 3165b8e80941Smrg dri2_sync->base.SyncStatus = EGL_SIGNALED_KHR; 3166b8e80941Smrg else 3167b8e80941Smrg ret = EGL_TIMEOUT_EXPIRED_KHR; 3168b8e80941Smrg break; 3169848b8605Smrg 3170b8e80941Smrg case EGL_SYNC_REUSABLE_KHR: 3171b8e80941Smrg if (dri2_ctx && dri2_sync->base.SyncStatus == EGL_UNSIGNALED_KHR && 3172b8e80941Smrg (flags & EGL_SYNC_FLUSH_COMMANDS_BIT_KHR)) { 3173b8e80941Smrg /* flush context if EGL_SYNC_FLUSH_COMMANDS_BIT_KHR is set */ 3174b8e80941Smrg dri2_gl_flush(); 3175b8e80941Smrg } 3176b8e80941Smrg 3177b8e80941Smrg /* if timeout is EGL_FOREVER_KHR, it should wait without any timeout.*/ 3178b8e80941Smrg if (timeout == EGL_FOREVER_KHR) { 3179b8e80941Smrg mtx_lock(&dri2_sync->mutex); 3180b8e80941Smrg cnd_wait(&dri2_sync->cond, &dri2_sync->mutex); 3181b8e80941Smrg mtx_unlock(&dri2_sync->mutex); 3182b8e80941Smrg } else { 3183b8e80941Smrg /* if reusable sync has not been yet signaled */ 3184b8e80941Smrg if (dri2_sync->base.SyncStatus != EGL_SIGNALED_KHR) { 3185b8e80941Smrg /* timespecs for cnd_timedwait */ 3186b8e80941Smrg struct timespec current; 3187b8e80941Smrg struct timespec expire; 3188b8e80941Smrg 3189b8e80941Smrg /* We override the clock to monotonic when creating the condition 3190b8e80941Smrg * variable. */ 3191b8e80941Smrg clock_gettime(CLOCK_MONOTONIC, ¤t); 3192b8e80941Smrg 3193b8e80941Smrg /* calculating when to expire */ 3194b8e80941Smrg expire.tv_nsec = timeout % 1000000000L; 3195b8e80941Smrg expire.tv_sec = timeout / 1000000000L; 3196b8e80941Smrg 3197b8e80941Smrg expire.tv_nsec += current.tv_nsec; 3198b8e80941Smrg expire.tv_sec += current.tv_sec; 3199b8e80941Smrg 3200b8e80941Smrg /* expire.nsec now is a number between 0 and 1999999998 */ 3201b8e80941Smrg if (expire.tv_nsec > 999999999L) { 3202b8e80941Smrg expire.tv_sec++; 3203b8e80941Smrg expire.tv_nsec -= 1000000000L; 3204b8e80941Smrg } 3205b8e80941Smrg 3206b8e80941Smrg mtx_lock(&dri2_sync->mutex); 3207b8e80941Smrg ret = cnd_timedwait(&dri2_sync->cond, &dri2_sync->mutex, &expire); 3208b8e80941Smrg mtx_unlock(&dri2_sync->mutex); 3209b8e80941Smrg 3210b8e80941Smrg if (ret == thrd_busy) { 3211b8e80941Smrg if (dri2_sync->base.SyncStatus == EGL_UNSIGNALED_KHR) { 3212b8e80941Smrg ret = EGL_TIMEOUT_EXPIRED_KHR; 3213b8e80941Smrg } else { 3214b8e80941Smrg _eglError(EGL_BAD_ACCESS, "eglClientWaitSyncKHR"); 3215b8e80941Smrg ret = EGL_FALSE; 3216b8e80941Smrg } 3217b8e80941Smrg } 3218b8e80941Smrg } 3219b8e80941Smrg } 3220b8e80941Smrg break; 3221b8e80941Smrg } 3222b8e80941Smrg dri2_egl_unref_sync(dri2_dpy, dri2_sync); 3223b8e80941Smrg 3224b8e80941Smrg return ret; 3225b8e80941Smrg} 3226b8e80941Smrg 3227b8e80941Smrgstatic EGLBoolean 3228b8e80941Smrgdri2_signal_sync(_EGLDriver *drv, _EGLDisplay *disp, _EGLSync *sync, 3229b8e80941Smrg EGLenum mode) 3230b8e80941Smrg{ 3231b8e80941Smrg struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync); 3232b8e80941Smrg EGLint ret; 3233b8e80941Smrg 3234b8e80941Smrg if (sync->Type != EGL_SYNC_REUSABLE_KHR) 3235b8e80941Smrg return _eglError(EGL_BAD_MATCH, "eglSignalSyncKHR"); 3236b8e80941Smrg 3237b8e80941Smrg if (mode != EGL_SIGNALED_KHR && mode != EGL_UNSIGNALED_KHR) 3238b8e80941Smrg return _eglError(EGL_BAD_ATTRIBUTE, "eglSignalSyncKHR"); 3239b8e80941Smrg 3240b8e80941Smrg dri2_sync->base.SyncStatus = mode; 3241b8e80941Smrg 3242b8e80941Smrg if (mode == EGL_SIGNALED_KHR) { 3243b8e80941Smrg ret = cnd_broadcast(&dri2_sync->cond); 3244b8e80941Smrg 3245b8e80941Smrg /* fail to broadcast */ 3246b8e80941Smrg if (ret) 3247b8e80941Smrg return _eglError(EGL_BAD_ACCESS, "eglSignalSyncKHR"); 3248848b8605Smrg } 3249848b8605Smrg 3250b8e80941Smrg return EGL_TRUE; 3251b8e80941Smrg} 3252b8e80941Smrg 3253b8e80941Smrgstatic EGLint 3254b8e80941Smrgdri2_server_wait_sync(_EGLDriver *drv, _EGLDisplay *disp, _EGLSync *sync) 3255b8e80941Smrg{ 3256b8e80941Smrg _EGLContext *ctx = _eglGetCurrentContext(); 3257b8e80941Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 3258b8e80941Smrg struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); 3259b8e80941Smrg struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync); 3260b8e80941Smrg 3261b8e80941Smrg dri2_dpy->fence->server_wait_sync(dri2_ctx->dri_context, 3262b8e80941Smrg dri2_sync->fence, 0); 3263b8e80941Smrg return EGL_TRUE; 3264b8e80941Smrg} 3265b8e80941Smrg 3266b8e80941Smrgstatic int 3267b8e80941Smrgdri2_interop_query_device_info(_EGLDisplay *disp, _EGLContext *ctx, 3268b8e80941Smrg struct mesa_glinterop_device_info *out) 3269b8e80941Smrg{ 3270b8e80941Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 3271b8e80941Smrg struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); 3272b8e80941Smrg 3273b8e80941Smrg if (!dri2_dpy->interop) 3274b8e80941Smrg return MESA_GLINTEROP_UNSUPPORTED; 3275b8e80941Smrg 3276b8e80941Smrg return dri2_dpy->interop->query_device_info(dri2_ctx->dri_context, out); 3277b8e80941Smrg} 3278b8e80941Smrg 3279b8e80941Smrgstatic int 3280b8e80941Smrgdri2_interop_export_object(_EGLDisplay *disp, _EGLContext *ctx, 3281b8e80941Smrg struct mesa_glinterop_export_in *in, 3282b8e80941Smrg struct mesa_glinterop_export_out *out) 3283b8e80941Smrg{ 3284b8e80941Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 3285b8e80941Smrg struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); 3286b8e80941Smrg 3287b8e80941Smrg if (!dri2_dpy->interop) 3288b8e80941Smrg return MESA_GLINTEROP_UNSUPPORTED; 3289b8e80941Smrg 3290b8e80941Smrg return dri2_dpy->interop->export_object(dri2_ctx->dri_context, in, out); 3291b8e80941Smrg} 3292b8e80941Smrg 3293b8e80941Smrg/** 3294b8e80941Smrg * This is the main entrypoint into the driver, called by libEGL. 3295b8e80941Smrg * Gets an _EGLDriver object and init its dispatch table. 3296b8e80941Smrg */ 3297b8e80941Smrgvoid 3298b8e80941Smrg_eglInitDriver(_EGLDriver *dri2_drv) 3299b8e80941Smrg{ 3300b8e80941Smrg dri2_drv->API.Initialize = dri2_initialize; 3301b8e80941Smrg dri2_drv->API.Terminate = dri2_terminate; 3302b8e80941Smrg dri2_drv->API.CreateContext = dri2_create_context; 3303b8e80941Smrg dri2_drv->API.DestroyContext = dri2_destroy_context; 3304b8e80941Smrg dri2_drv->API.MakeCurrent = dri2_make_current; 3305b8e80941Smrg dri2_drv->API.CreateWindowSurface = dri2_create_window_surface; 3306b8e80941Smrg dri2_drv->API.CreatePixmapSurface = dri2_create_pixmap_surface; 3307b8e80941Smrg dri2_drv->API.CreatePbufferSurface = dri2_create_pbuffer_surface; 3308b8e80941Smrg dri2_drv->API.DestroySurface = dri2_destroy_surface; 3309b8e80941Smrg dri2_drv->API.GetProcAddress = dri2_get_proc_address; 3310b8e80941Smrg dri2_drv->API.WaitClient = dri2_wait_client; 3311b8e80941Smrg dri2_drv->API.WaitNative = dri2_wait_native; 3312b8e80941Smrg dri2_drv->API.BindTexImage = dri2_bind_tex_image; 3313b8e80941Smrg dri2_drv->API.ReleaseTexImage = dri2_release_tex_image; 3314b8e80941Smrg dri2_drv->API.SwapInterval = dri2_swap_interval; 3315b8e80941Smrg dri2_drv->API.SwapBuffers = dri2_swap_buffers; 3316b8e80941Smrg dri2_drv->API.SwapBuffersWithDamageEXT = dri2_swap_buffers_with_damage; 3317b8e80941Smrg dri2_drv->API.SwapBuffersRegionNOK = dri2_swap_buffers_region; 3318b8e80941Smrg dri2_drv->API.SetDamageRegion = dri2_set_damage_region; 3319b8e80941Smrg dri2_drv->API.PostSubBufferNV = dri2_post_sub_buffer; 3320b8e80941Smrg dri2_drv->API.CopyBuffers = dri2_copy_buffers, 3321b8e80941Smrg dri2_drv->API.QueryBufferAge = dri2_query_buffer_age; 3322b8e80941Smrg dri2_drv->API.CreateImageKHR = dri2_create_image; 3323b8e80941Smrg dri2_drv->API.DestroyImageKHR = dri2_destroy_image_khr; 3324b8e80941Smrg dri2_drv->API.CreateWaylandBufferFromImageWL = dri2_create_wayland_buffer_from_image; 3325b8e80941Smrg dri2_drv->API.QuerySurface = dri2_query_surface; 3326b8e80941Smrg dri2_drv->API.QueryDriverName = dri2_query_driver_name; 3327b8e80941Smrg dri2_drv->API.QueryDriverConfig = dri2_query_driver_config; 3328b8e80941Smrg#ifdef HAVE_LIBDRM 3329b8e80941Smrg dri2_drv->API.CreateDRMImageMESA = dri2_create_drm_image_mesa; 3330b8e80941Smrg dri2_drv->API.ExportDRMImageMESA = dri2_export_drm_image_mesa; 3331b8e80941Smrg dri2_drv->API.ExportDMABUFImageQueryMESA = dri2_export_dma_buf_image_query_mesa; 3332b8e80941Smrg dri2_drv->API.ExportDMABUFImageMESA = dri2_export_dma_buf_image_mesa; 3333b8e80941Smrg dri2_drv->API.QueryDmaBufFormatsEXT = dri2_query_dma_buf_formats; 3334b8e80941Smrg dri2_drv->API.QueryDmaBufModifiersEXT = dri2_query_dma_buf_modifiers; 3335848b8605Smrg#endif 3336848b8605Smrg#ifdef HAVE_WAYLAND_PLATFORM 3337b8e80941Smrg dri2_drv->API.BindWaylandDisplayWL = dri2_bind_wayland_display_wl; 3338b8e80941Smrg dri2_drv->API.UnbindWaylandDisplayWL = dri2_unbind_wayland_display_wl; 3339b8e80941Smrg dri2_drv->API.QueryWaylandBufferWL = dri2_query_wayland_buffer_wl; 3340848b8605Smrg#endif 3341b8e80941Smrg dri2_drv->API.GetSyncValuesCHROMIUM = dri2_get_sync_values_chromium; 3342b8e80941Smrg dri2_drv->API.CreateSyncKHR = dri2_create_sync; 3343b8e80941Smrg dri2_drv->API.ClientWaitSyncKHR = dri2_client_wait_sync; 3344b8e80941Smrg dri2_drv->API.SignalSyncKHR = dri2_signal_sync; 3345b8e80941Smrg dri2_drv->API.WaitSyncKHR = dri2_server_wait_sync; 3346b8e80941Smrg dri2_drv->API.DestroySyncKHR = dri2_destroy_sync; 3347b8e80941Smrg dri2_drv->API.GLInteropQueryDeviceInfo = dri2_interop_query_device_info; 3348b8e80941Smrg dri2_drv->API.GLInteropExportObject = dri2_interop_export_object; 3349b8e80941Smrg dri2_drv->API.DupNativeFenceFDANDROID = dri2_dup_native_fence_fd; 3350b8e80941Smrg dri2_drv->API.SetBlobCacheFuncsANDROID = dri2_set_blob_cache_funcs; 3351848b8605Smrg} 3352