1cdc920a0Smrg/* 2cdc920a0Smrg * Copyright © 2010 Intel Corporation 3cdc920a0Smrg * 4cdc920a0Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5cdc920a0Smrg * copy of this software and associated documentation files (the "Software"), 6cdc920a0Smrg * to deal in the Software without restriction, including without limitation 7cdc920a0Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8cdc920a0Smrg * and/or sell copies of the Software, and to permit persons to whom the 9cdc920a0Smrg * Software is furnished to do so, subject to the following conditions: 10cdc920a0Smrg * 11cdc920a0Smrg * The above copyright notice and this permission notice (including the next 12cdc920a0Smrg * paragraph) shall be included in all copies or substantial portions of the 13cdc920a0Smrg * Software. 14cdc920a0Smrg * 15cdc920a0Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16cdc920a0Smrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17cdc920a0Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18cdc920a0Smrg * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19cdc920a0Smrg * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20cdc920a0Smrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21cdc920a0Smrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22cdc920a0Smrg * DEALINGS IN THE SOFTWARE. 23cdc920a0Smrg * 24cdc920a0Smrg * Authors: 25cdc920a0Smrg * Kristian Høgsberg <krh@bitplanet.net> 26cdc920a0Smrg */ 27cdc920a0Smrg 2801e04c3fSmrg#include <stdbool.h> 2901e04c3fSmrg#include <stdint.h> 3001e04c3fSmrg#include <stdbool.h> 31cdc920a0Smrg#include <stdlib.h> 32cdc920a0Smrg#include <string.h> 33cdc920a0Smrg#include <stdio.h> 34cdc920a0Smrg#include <limits.h> 35cdc920a0Smrg#include <dlfcn.h> 36cdc920a0Smrg#include <fcntl.h> 37cdc920a0Smrg#include <errno.h> 38cdc920a0Smrg#include <unistd.h> 3901e04c3fSmrg#include <c11/threads.h> 4001e04c3fSmrg#include <time.h> 41af69d88dSmrg#ifdef HAVE_LIBDRM 42cdc920a0Smrg#include <xf86drm.h> 437e102996Smaya#include "drm-uapi/drm_fourcc.h" 44af69d88dSmrg#endif 45cdc920a0Smrg#include <GL/gl.h> 46cdc920a0Smrg#include <GL/internal/dri_interface.h> 473464ebd5Sriastradh#include <sys/types.h> 483464ebd5Sriastradh#include <sys/stat.h> 49cdc920a0Smrg 50af69d88dSmrg#ifdef HAVE_WAYLAND_PLATFORM 5101e04c3fSmrg#include <wayland-client.h> 52af69d88dSmrg#include "wayland-drm.h" 53af69d88dSmrg#include "wayland-drm-client-protocol.h" 5401e04c3fSmrg#include "linux-dmabuf-unstable-v1-client-protocol.h" 5501e04c3fSmrg#endif 5601e04c3fSmrg 5701e04c3fSmrg#ifdef HAVE_X11_PLATFORM 5801e04c3fSmrg#include "X11/Xlibint.h" 59af69d88dSmrg#endif 60af69d88dSmrg 617e102996Smaya#include "egldefines.h" 623464ebd5Sriastradh#include "egl_dri2.h" 6301e04c3fSmrg#include "GL/mesa_glinterop.h" 6401e04c3fSmrg#include "loader/loader.h" 657ec681f3Smrg#include "util/libsync.h" 667ec681f3Smrg#include "util/os_file.h" 6701e04c3fSmrg#include "util/u_atomic.h" 6801e04c3fSmrg#include "util/u_vector.h" 6901e04c3fSmrg#include "mapi/glapi/glapi.h" 707ec681f3Smrg#include "util/bitscan.h" 717ec681f3Smrg#include "util/u_math.h" 727e102996Smaya 7301e04c3fSmrg#define NUM_ATTRIBS 12 7401e04c3fSmrg 757ec681f3Smrgstatic const struct dri2_pbuffer_visual { 767ec681f3Smrg const char *format_name; 777ec681f3Smrg unsigned int dri_image_format; 787ec681f3Smrg int rgba_shifts[4]; 797ec681f3Smrg unsigned int rgba_sizes[4]; 807ec681f3Smrg} dri2_pbuffer_visuals[] = { 817ec681f3Smrg { 827ec681f3Smrg "ABGR16F", 837ec681f3Smrg __DRI_IMAGE_FORMAT_ABGR16161616F, 847ec681f3Smrg { 0, 16, 32, 48 }, 857ec681f3Smrg { 16, 16, 16, 16 } 867ec681f3Smrg }, 877ec681f3Smrg { 887ec681f3Smrg "XBGR16F", 897ec681f3Smrg __DRI_IMAGE_FORMAT_XBGR16161616F, 907ec681f3Smrg { 0, 16, 32, -1 }, 917ec681f3Smrg { 16, 16, 16, 0 } 927ec681f3Smrg }, 937ec681f3Smrg { 947ec681f3Smrg "A2RGB10", 957ec681f3Smrg __DRI_IMAGE_FORMAT_ARGB2101010, 967ec681f3Smrg { 20, 10, 0, 30 }, 977ec681f3Smrg { 10, 10, 10, 2 } 987ec681f3Smrg }, 997ec681f3Smrg { 1007ec681f3Smrg "X2RGB10", 1017ec681f3Smrg __DRI_IMAGE_FORMAT_XRGB2101010, 1027ec681f3Smrg { 20, 10, 0, -1 }, 1037ec681f3Smrg { 10, 10, 10, 0 } 1047ec681f3Smrg }, 1057ec681f3Smrg { 1067ec681f3Smrg "ARGB8888", 1077ec681f3Smrg __DRI_IMAGE_FORMAT_ARGB8888, 1087ec681f3Smrg { 16, 8, 0, 24 }, 1097ec681f3Smrg { 8, 8, 8, 8 } 1107ec681f3Smrg }, 1117ec681f3Smrg { 1127ec681f3Smrg "RGB888", 1137ec681f3Smrg __DRI_IMAGE_FORMAT_XRGB8888, 1147ec681f3Smrg { 16, 8, 0, -1 }, 1157ec681f3Smrg { 8, 8, 8, 0 } 1167ec681f3Smrg }, 1177ec681f3Smrg { 1187ec681f3Smrg "RGB565", 1197ec681f3Smrg __DRI_IMAGE_FORMAT_RGB565, 1207ec681f3Smrg { 11, 5, 0, -1 }, 1217ec681f3Smrg { 5, 6, 5, 0 } 1227ec681f3Smrg }, 1237ec681f3Smrg}; 1247ec681f3Smrg 12501e04c3fSmrgstatic void 12601e04c3fSmrgdri_set_background_context(void *loaderPrivate) 12701e04c3fSmrg{ 12801e04c3fSmrg _EGLContext *ctx = _eglGetCurrentContext(); 12901e04c3fSmrg _EGLThreadInfo *t = _eglGetCurrentThread(); 13001e04c3fSmrg 13101e04c3fSmrg _eglBindContextToThread(ctx, t); 13201e04c3fSmrg} 13301e04c3fSmrg 13401e04c3fSmrgstatic void 13501e04c3fSmrgdri2_gl_flush() 13601e04c3fSmrg{ 13701e04c3fSmrg static void (*glFlush)(void); 13801e04c3fSmrg static mtx_t glFlushMutex = _MTX_INITIALIZER_NP; 13901e04c3fSmrg 14001e04c3fSmrg mtx_lock(&glFlushMutex); 14101e04c3fSmrg if (!glFlush) 14201e04c3fSmrg glFlush = _glapi_get_proc_address("glFlush"); 14301e04c3fSmrg mtx_unlock(&glFlushMutex); 14401e04c3fSmrg 14501e04c3fSmrg /* if glFlush is not available things are horribly broken */ 14601e04c3fSmrg if (!glFlush) { 14701e04c3fSmrg _eglLog(_EGL_WARNING, "DRI2: failed to find glFlush entry point"); 14801e04c3fSmrg return; 14901e04c3fSmrg } 15001e04c3fSmrg 15101e04c3fSmrg glFlush(); 15201e04c3fSmrg} 15301e04c3fSmrg 15401e04c3fSmrgstatic GLboolean 15501e04c3fSmrgdri_is_thread_safe(void *loaderPrivate) 15601e04c3fSmrg{ 15701e04c3fSmrg struct dri2_egl_surface *dri2_surf = loaderPrivate; 1587ec681f3Smrg UNUSED _EGLDisplay *display = dri2_surf->base.Resource.Display; 15901e04c3fSmrg 16001e04c3fSmrg#ifdef HAVE_X11_PLATFORM 16101e04c3fSmrg Display *xdpy = (Display*)display->PlatformDisplay; 16201e04c3fSmrg 16301e04c3fSmrg /* Check Xlib is running in thread safe mode when running on EGL/X11-xlib 16401e04c3fSmrg * platform 16501e04c3fSmrg * 16601e04c3fSmrg * 'lock_fns' is the XLockDisplay function pointer of the X11 display 'dpy'. 16701e04c3fSmrg * It wll be NULL if XInitThreads wasn't called. 16801e04c3fSmrg */ 16901e04c3fSmrg if (display->Platform == _EGL_PLATFORM_X11 && xdpy && !xdpy->lock_fns) 17001e04c3fSmrg return false; 17101e04c3fSmrg#endif 17201e04c3fSmrg 17301e04c3fSmrg return true; 17401e04c3fSmrg} 17501e04c3fSmrg 17601e04c3fSmrgconst __DRIbackgroundCallableExtension background_callable_extension = { 17701e04c3fSmrg .base = { __DRI_BACKGROUND_CALLABLE, 2 }, 17801e04c3fSmrg 17901e04c3fSmrg .setBackgroundContext = dri_set_background_context, 18001e04c3fSmrg .isThreadSafe = dri_is_thread_safe, 18101e04c3fSmrg}; 182cdc920a0Smrg 1833464ebd5Sriastradhconst __DRIuseInvalidateExtension use_invalidate = { 184af69d88dSmrg .base = { __DRI_USE_INVALIDATE, 1 } 185cdc920a0Smrg}; 186cdc920a0Smrg 1877ec681f3Smrgstatic void 1887ec681f3Smrgdri2_get_pbuffer_drawable_info(__DRIdrawable * draw, 1897ec681f3Smrg int *x, int *y, int *w, int *h, 1907ec681f3Smrg void *loaderPrivate) 1917ec681f3Smrg{ 1927ec681f3Smrg struct dri2_egl_surface *dri2_surf = loaderPrivate; 1937ec681f3Smrg 1947ec681f3Smrg *x = *y = 0; 1957ec681f3Smrg *w = dri2_surf->base.Width; 1967ec681f3Smrg *h = dri2_surf->base.Height; 1977ec681f3Smrg} 1987ec681f3Smrg 1997ec681f3Smrgstatic int 2007ec681f3Smrgdri2_get_bytes_per_pixel(struct dri2_egl_surface *dri2_surf) 2017ec681f3Smrg{ 2027ec681f3Smrg const int depth = dri2_surf->base.Config->BufferSize; 2037ec681f3Smrg return depth ? util_next_power_of_two(depth / 8) : 0; 2047ec681f3Smrg} 2057ec681f3Smrg 2067ec681f3Smrgstatic void 2077ec681f3Smrgdri2_put_image(__DRIdrawable * draw, int op, 2087ec681f3Smrg int x, int y, int w, int h, 2097ec681f3Smrg char *data, void *loaderPrivate) 2107ec681f3Smrg{ 2117ec681f3Smrg struct dri2_egl_surface *dri2_surf = loaderPrivate; 2127ec681f3Smrg const int bpp = dri2_get_bytes_per_pixel(dri2_surf); 2137ec681f3Smrg const int width = dri2_surf->base.Width; 2147ec681f3Smrg const int height = dri2_surf->base.Height; 2157ec681f3Smrg const int dst_stride = width*bpp; 2167ec681f3Smrg const int src_stride = w*bpp; 2177ec681f3Smrg const int x_offset = x*bpp; 2187ec681f3Smrg int copy_width = src_stride; 2197ec681f3Smrg 2207ec681f3Smrg if (!dri2_surf->swrast_device_buffer) 2217ec681f3Smrg dri2_surf->swrast_device_buffer = malloc(height*dst_stride); 2227ec681f3Smrg 2237ec681f3Smrg if (dri2_surf->swrast_device_buffer) { 2247ec681f3Smrg const char *src = data; 2257ec681f3Smrg char *dst = dri2_surf->swrast_device_buffer; 2267ec681f3Smrg 2277ec681f3Smrg dst += x_offset; 2287ec681f3Smrg dst += y*dst_stride; 2297ec681f3Smrg 2307ec681f3Smrg /* Drivers are allowed to submit OOB PutImage requests, so clip here. */ 2317ec681f3Smrg if (copy_width > dst_stride - x_offset) 2327ec681f3Smrg copy_width = dst_stride - x_offset; 2337ec681f3Smrg if (h > height - y) 2347ec681f3Smrg h = height - y; 2357ec681f3Smrg 2367ec681f3Smrg for (; 0 < h; --h) { 2377ec681f3Smrg memcpy(dst, src, copy_width); 2387ec681f3Smrg dst += dst_stride; 2397ec681f3Smrg src += src_stride; 2407ec681f3Smrg } 2417ec681f3Smrg } 2427ec681f3Smrg} 2437ec681f3Smrg 2447ec681f3Smrgstatic void 2457ec681f3Smrgdri2_get_image(__DRIdrawable * read, 2467ec681f3Smrg int x, int y, int w, int h, 2477ec681f3Smrg char *data, void *loaderPrivate) 2487ec681f3Smrg{ 2497ec681f3Smrg struct dri2_egl_surface *dri2_surf = loaderPrivate; 2507ec681f3Smrg const int bpp = dri2_get_bytes_per_pixel(dri2_surf); 2517ec681f3Smrg const int width = dri2_surf->base.Width; 2527ec681f3Smrg const int height = dri2_surf->base.Height; 2537ec681f3Smrg const int src_stride = width*bpp; 2547ec681f3Smrg const int dst_stride = w*bpp; 2557ec681f3Smrg const int x_offset = x*bpp; 2567ec681f3Smrg int copy_width = dst_stride; 2577ec681f3Smrg const char *src = dri2_surf->swrast_device_buffer; 2587ec681f3Smrg char *dst = data; 2597ec681f3Smrg 2607ec681f3Smrg if (!src) { 2617ec681f3Smrg memset(data, 0, copy_width * h); 2627ec681f3Smrg return; 2637ec681f3Smrg } 2647ec681f3Smrg 2657ec681f3Smrg src += x_offset; 2667ec681f3Smrg src += y*src_stride; 2677ec681f3Smrg 2687ec681f3Smrg /* Drivers are allowed to submit OOB GetImage requests, so clip here. */ 2697ec681f3Smrg if (copy_width > src_stride - x_offset) 2707ec681f3Smrg copy_width = src_stride - x_offset; 2717ec681f3Smrg if (h > height - y) 2727ec681f3Smrg h = height - y; 2737ec681f3Smrg 2747ec681f3Smrg for (; 0 < h; --h) { 2757ec681f3Smrg memcpy(dst, src, copy_width); 2767ec681f3Smrg src += src_stride; 2777ec681f3Smrg dst += dst_stride; 2787ec681f3Smrg } 2797ec681f3Smrg 2807ec681f3Smrg} 2817ec681f3Smrg 2827ec681f3Smrg/* HACK: technically we should have swrast_null, instead of these. 2837ec681f3Smrg */ 2847ec681f3Smrgconst __DRIswrastLoaderExtension swrast_pbuffer_loader_extension = { 2857ec681f3Smrg .base = { __DRI_SWRAST_LOADER, 1 }, 2867ec681f3Smrg .getDrawableInfo = dri2_get_pbuffer_drawable_info, 2877ec681f3Smrg .putImage = dri2_put_image, 2887ec681f3Smrg .getImage = dri2_get_image, 2897ec681f3Smrg}; 2907ec681f3Smrg 29101e04c3fSmrgstatic const EGLint dri2_to_egl_attribute_map[__DRI_ATTRIB_MAX] = { 29201e04c3fSmrg [__DRI_ATTRIB_BUFFER_SIZE ] = EGL_BUFFER_SIZE, 29301e04c3fSmrg [__DRI_ATTRIB_LEVEL] = EGL_LEVEL, 29401e04c3fSmrg [__DRI_ATTRIB_LUMINANCE_SIZE] = EGL_LUMINANCE_SIZE, 29501e04c3fSmrg [__DRI_ATTRIB_DEPTH_SIZE] = EGL_DEPTH_SIZE, 29601e04c3fSmrg [__DRI_ATTRIB_STENCIL_SIZE] = EGL_STENCIL_SIZE, 29701e04c3fSmrg [__DRI_ATTRIB_SAMPLE_BUFFERS] = EGL_SAMPLE_BUFFERS, 29801e04c3fSmrg [__DRI_ATTRIB_SAMPLES] = EGL_SAMPLES, 29901e04c3fSmrg [__DRI_ATTRIB_MAX_PBUFFER_WIDTH] = EGL_MAX_PBUFFER_WIDTH, 30001e04c3fSmrg [__DRI_ATTRIB_MAX_PBUFFER_HEIGHT] = EGL_MAX_PBUFFER_HEIGHT, 30101e04c3fSmrg [__DRI_ATTRIB_MAX_PBUFFER_PIXELS] = EGL_MAX_PBUFFER_PIXELS, 30201e04c3fSmrg [__DRI_ATTRIB_MAX_SWAP_INTERVAL] = EGL_MAX_SWAP_INTERVAL, 30301e04c3fSmrg [__DRI_ATTRIB_MIN_SWAP_INTERVAL] = EGL_MIN_SWAP_INTERVAL, 30401e04c3fSmrg [__DRI_ATTRIB_YINVERTED] = EGL_Y_INVERTED_NOK, 305cdc920a0Smrg}; 306cdc920a0Smrg 30701e04c3fSmrgconst __DRIconfig * 30801e04c3fSmrgdri2_get_dri_config(struct dri2_egl_config *conf, EGLint surface_type, 30901e04c3fSmrg EGLenum colorspace) 31001e04c3fSmrg{ 31101e04c3fSmrg const bool double_buffer = surface_type == EGL_WINDOW_BIT; 31201e04c3fSmrg const bool srgb = colorspace == EGL_GL_COLORSPACE_SRGB_KHR; 31301e04c3fSmrg 31401e04c3fSmrg return conf->dri_config[double_buffer][srgb]; 31501e04c3fSmrg} 31601e04c3fSmrg 3173464ebd5Sriastradhstatic EGLBoolean 3183464ebd5Sriastradhdri2_match_config(const _EGLConfig *conf, const _EGLConfig *criteria) 3193464ebd5Sriastradh{ 3203464ebd5Sriastradh if (_eglCompareConfigs(conf, criteria, NULL, EGL_FALSE) != 0) 3213464ebd5Sriastradh return EGL_FALSE; 3223464ebd5Sriastradh 3233464ebd5Sriastradh if (!_eglMatchConfig(conf, criteria)) 3243464ebd5Sriastradh return EGL_FALSE; 3253464ebd5Sriastradh 3263464ebd5Sriastradh return EGL_TRUE; 3273464ebd5Sriastradh} 3283464ebd5Sriastradh 3297ec681f3Smrgvoid 3307ec681f3Smrgdri2_get_shifts_and_sizes(const __DRIcoreExtension *core, 3317ec681f3Smrg const __DRIconfig *config, int *shifts, 3327ec681f3Smrg unsigned int *sizes) 3337ec681f3Smrg{ 3347ec681f3Smrg unsigned int mask; 3357ec681f3Smrg 3367ec681f3Smrg if (core->getConfigAttrib(config, __DRI_ATTRIB_RED_SHIFT, (unsigned int *)&shifts[0])) { 3377ec681f3Smrg core->getConfigAttrib(config, __DRI_ATTRIB_GREEN_SHIFT, (unsigned int *)&shifts[1]); 3387ec681f3Smrg core->getConfigAttrib(config, __DRI_ATTRIB_BLUE_SHIFT, (unsigned int *)&shifts[2]); 3397ec681f3Smrg core->getConfigAttrib(config, __DRI_ATTRIB_ALPHA_SHIFT, (unsigned int *)&shifts[3]); 3407ec681f3Smrg } else { 3417ec681f3Smrg /* Driver isn't exposing shifts, so convert masks to shifts */ 3427ec681f3Smrg core->getConfigAttrib(config, __DRI_ATTRIB_RED_MASK, &mask); 3437ec681f3Smrg shifts[0] = ffs(mask) - 1; 3447ec681f3Smrg core->getConfigAttrib(config, __DRI_ATTRIB_GREEN_MASK, &mask); 3457ec681f3Smrg shifts[1] = ffs(mask) - 1; 3467ec681f3Smrg core->getConfigAttrib(config, __DRI_ATTRIB_BLUE_MASK, &mask); 3477ec681f3Smrg shifts[2] = ffs(mask) - 1; 3487ec681f3Smrg core->getConfigAttrib(config, __DRI_ATTRIB_ALPHA_MASK, &mask); 3497ec681f3Smrg shifts[3] = ffs(mask) - 1; 3507ec681f3Smrg } 3517ec681f3Smrg 3527ec681f3Smrg core->getConfigAttrib(config, __DRI_ATTRIB_RED_SIZE, &sizes[0]); 3537ec681f3Smrg core->getConfigAttrib(config, __DRI_ATTRIB_GREEN_SIZE, &sizes[1]); 3547ec681f3Smrg core->getConfigAttrib(config, __DRI_ATTRIB_BLUE_SIZE, &sizes[2]); 3557ec681f3Smrg core->getConfigAttrib(config, __DRI_ATTRIB_ALPHA_SIZE, &sizes[3]); 3567ec681f3Smrg} 3577ec681f3Smrg 3587ec681f3Smrgvoid 3597ec681f3Smrgdri2_get_render_type_float(const __DRIcoreExtension *core, 3607ec681f3Smrg const __DRIconfig *config, 3617ec681f3Smrg bool *is_float) 3627ec681f3Smrg{ 3637ec681f3Smrg unsigned int render_type; 3647ec681f3Smrg 3657ec681f3Smrg core->getConfigAttrib(config, __DRI_ATTRIB_RENDER_TYPE, &render_type); 3667ec681f3Smrg *is_float = (render_type & __DRI_ATTRIB_FLOAT_BIT) ? true : false; 3677ec681f3Smrg} 3687ec681f3Smrg 3697ec681f3Smrgunsigned int 3707ec681f3Smrgdri2_image_format_for_pbuffer_config(struct dri2_egl_display *dri2_dpy, 3717ec681f3Smrg const __DRIconfig *config) 3727ec681f3Smrg{ 3737ec681f3Smrg int shifts[4]; 3747ec681f3Smrg unsigned int sizes[4]; 3757ec681f3Smrg 3767ec681f3Smrg dri2_get_shifts_and_sizes(dri2_dpy->core, config, shifts, sizes); 3777ec681f3Smrg 3787ec681f3Smrg for (unsigned i = 0; i < ARRAY_SIZE(dri2_pbuffer_visuals); ++i) { 3797ec681f3Smrg const struct dri2_pbuffer_visual *visual = &dri2_pbuffer_visuals[i]; 3807ec681f3Smrg 3817ec681f3Smrg if (shifts[0] == visual->rgba_shifts[0] && 3827ec681f3Smrg shifts[1] == visual->rgba_shifts[1] && 3837ec681f3Smrg shifts[2] == visual->rgba_shifts[2] && 3847ec681f3Smrg shifts[3] == visual->rgba_shifts[3] && 3857ec681f3Smrg sizes[0] == visual->rgba_sizes[0] && 3867ec681f3Smrg sizes[1] == visual->rgba_sizes[1] && 3877ec681f3Smrg sizes[2] == visual->rgba_sizes[2] && 3887ec681f3Smrg sizes[3] == visual->rgba_sizes[3]) { 3897ec681f3Smrg return visual->dri_image_format; 3907ec681f3Smrg } 3917ec681f3Smrg } 3927ec681f3Smrg 3937ec681f3Smrg return __DRI_IMAGE_FORMAT_NONE; 3947ec681f3Smrg} 3957ec681f3Smrg 3963464ebd5Sriastradhstruct dri2_egl_config * 397cdc920a0Smrgdri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id, 39801e04c3fSmrg EGLint surface_type, const EGLint *attr_list, 3997ec681f3Smrg const int *rgba_shifts, const unsigned int *rgba_sizes) 400cdc920a0Smrg{ 401cdc920a0Smrg struct dri2_egl_config *conf; 40201e04c3fSmrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 403cdc920a0Smrg _EGLConfig base; 404cdc920a0Smrg unsigned int attrib, value, double_buffer; 40501e04c3fSmrg bool srgb = false; 406cdc920a0Smrg EGLint key, bind_to_texture_rgb, bind_to_texture_rgba; 4077ec681f3Smrg int dri_shifts[4] = { -1, -1, -1, -1 }; 4087ec681f3Smrg unsigned int dri_sizes[4] = { 0, 0, 0, 0 }; 4093464ebd5Sriastradh _EGLConfig *matching_config; 4103464ebd5Sriastradh EGLint num_configs = 0; 4113464ebd5Sriastradh EGLint config_id; 412cdc920a0Smrg 413cdc920a0Smrg _eglInitConfig(&base, disp, id); 41401e04c3fSmrg 4153464ebd5Sriastradh double_buffer = 0; 4163464ebd5Sriastradh bind_to_texture_rgb = 0; 4173464ebd5Sriastradh bind_to_texture_rgba = 0; 4183464ebd5Sriastradh 419993e1d59Smrg for (int i = 0; i < __DRI_ATTRIB_MAX; ++i) { 420993e1d59Smrg if (!dri2_dpy->core->indexConfigAttrib(dri_config, i, &attrib, &value)) 421993e1d59Smrg break; 422993e1d59Smrg 423cdc920a0Smrg switch (attrib) { 424cdc920a0Smrg case __DRI_ATTRIB_RENDER_TYPE: 4257ec681f3Smrg if (value & __DRI_ATTRIB_FLOAT_BIT) 4267ec681f3Smrg base.ComponentType = EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT; 42701e04c3fSmrg if (value & __DRI_ATTRIB_RGBA_BIT) 42801e04c3fSmrg value = EGL_RGB_BUFFER; 42901e04c3fSmrg else if (value & __DRI_ATTRIB_LUMINANCE_BIT) 43001e04c3fSmrg value = EGL_LUMINANCE_BUFFER; 43101e04c3fSmrg else 43201e04c3fSmrg return NULL; 4337ec681f3Smrg base.ColorBufferType = value; 43401e04c3fSmrg break; 435cdc920a0Smrg 436cdc920a0Smrg case __DRI_ATTRIB_CONFIG_CAVEAT: 437cdc920a0Smrg if (value & __DRI_ATTRIB_NON_CONFORMANT_CONFIG) 438cdc920a0Smrg value = EGL_NON_CONFORMANT_CONFIG; 439cdc920a0Smrg else if (value & __DRI_ATTRIB_SLOW_BIT) 440cdc920a0Smrg value = EGL_SLOW_CONFIG; 44101e04c3fSmrg else 44201e04c3fSmrg value = EGL_NONE; 4437ec681f3Smrg base.ConfigCaveat = value; 444cdc920a0Smrg break; 445cdc920a0Smrg 446cdc920a0Smrg case __DRI_ATTRIB_BIND_TO_TEXTURE_RGB: 44701e04c3fSmrg bind_to_texture_rgb = value; 44801e04c3fSmrg break; 449cdc920a0Smrg 450cdc920a0Smrg case __DRI_ATTRIB_BIND_TO_TEXTURE_RGBA: 45101e04c3fSmrg bind_to_texture_rgba = value; 45201e04c3fSmrg break; 453cdc920a0Smrg 454cdc920a0Smrg case __DRI_ATTRIB_DOUBLE_BUFFER: 45501e04c3fSmrg double_buffer = value; 45601e04c3fSmrg break; 457cdc920a0Smrg 4587ec681f3Smrg case __DRI_ATTRIB_RED_SIZE: 4597ec681f3Smrg dri_sizes[0] = value; 4607ec681f3Smrg base.RedSize = value; 4617ec681f3Smrg break; 4627ec681f3Smrg 463af69d88dSmrg case __DRI_ATTRIB_RED_MASK: 4647ec681f3Smrg dri_shifts[0] = ffs(value) - 1; 4657ec681f3Smrg break; 4667ec681f3Smrg 4677ec681f3Smrg case __DRI_ATTRIB_RED_SHIFT: 4687ec681f3Smrg dri_shifts[0] = value; 4697ec681f3Smrg break; 4707ec681f3Smrg 4717ec681f3Smrg case __DRI_ATTRIB_GREEN_SIZE: 4727ec681f3Smrg dri_sizes[1] = value; 4737ec681f3Smrg base.GreenSize = value; 474af69d88dSmrg break; 475af69d88dSmrg 476af69d88dSmrg case __DRI_ATTRIB_GREEN_MASK: 4777ec681f3Smrg dri_shifts[1] = ffs(value) - 1; 4787ec681f3Smrg break; 4797ec681f3Smrg 4807ec681f3Smrg case __DRI_ATTRIB_GREEN_SHIFT: 4817ec681f3Smrg dri_shifts[1] = value; 4827ec681f3Smrg break; 4837ec681f3Smrg 4847ec681f3Smrg case __DRI_ATTRIB_BLUE_SIZE: 4857ec681f3Smrg dri_sizes[2] = value; 4867ec681f3Smrg base.BlueSize = value; 487af69d88dSmrg break; 488af69d88dSmrg 489af69d88dSmrg case __DRI_ATTRIB_BLUE_MASK: 4907ec681f3Smrg dri_shifts[2] = ffs(value) - 1; 4917ec681f3Smrg break; 4927ec681f3Smrg 4937ec681f3Smrg case __DRI_ATTRIB_BLUE_SHIFT: 4947ec681f3Smrg dri_shifts[2] = value; 4957ec681f3Smrg break; 4967ec681f3Smrg 4977ec681f3Smrg case __DRI_ATTRIB_ALPHA_SIZE: 4987ec681f3Smrg dri_sizes[3] = value; 4997ec681f3Smrg base.AlphaSize = value; 500af69d88dSmrg break; 501af69d88dSmrg 502af69d88dSmrg case __DRI_ATTRIB_ALPHA_MASK: 5037ec681f3Smrg dri_shifts[3] = ffs(value) - 1; 5047ec681f3Smrg break; 5057ec681f3Smrg 5067ec681f3Smrg case __DRI_ATTRIB_ALPHA_SHIFT: 5077ec681f3Smrg dri_shifts[3] = value; 508af69d88dSmrg break; 509af69d88dSmrg 51001e04c3fSmrg case __DRI_ATTRIB_ACCUM_RED_SIZE: 51101e04c3fSmrg case __DRI_ATTRIB_ACCUM_GREEN_SIZE: 51201e04c3fSmrg case __DRI_ATTRIB_ACCUM_BLUE_SIZE: 51301e04c3fSmrg case __DRI_ATTRIB_ACCUM_ALPHA_SIZE: 51401e04c3fSmrg /* Don't expose visuals with the accumulation buffer. */ 51501e04c3fSmrg if (value > 0) 51601e04c3fSmrg return NULL; 51701e04c3fSmrg break; 51801e04c3fSmrg 51901e04c3fSmrg case __DRI_ATTRIB_FRAMEBUFFER_SRGB_CAPABLE: 52001e04c3fSmrg srgb = value != 0; 52101e04c3fSmrg if (!disp->Extensions.KHR_gl_colorspace && srgb) 52201e04c3fSmrg return NULL; 52301e04c3fSmrg break; 52401e04c3fSmrg 52501e04c3fSmrg case __DRI_ATTRIB_MAX_PBUFFER_WIDTH: 5267ec681f3Smrg base.MaxPbufferWidth = _EGL_MAX_PBUFFER_WIDTH; 52701e04c3fSmrg break; 52801e04c3fSmrg case __DRI_ATTRIB_MAX_PBUFFER_HEIGHT: 5297ec681f3Smrg base.MaxPbufferHeight = _EGL_MAX_PBUFFER_HEIGHT; 53001e04c3fSmrg break; 53101e04c3fSmrg case __DRI_ATTRIB_MUTABLE_RENDER_BUFFER: 53201e04c3fSmrg if (disp->Extensions.KHR_mutable_render_buffer) 53301e04c3fSmrg surface_type |= EGL_MUTABLE_RENDER_BUFFER_BIT_KHR; 53401e04c3fSmrg break; 535cdc920a0Smrg default: 53601e04c3fSmrg key = dri2_to_egl_attribute_map[attrib]; 53701e04c3fSmrg if (key != 0) 53801e04c3fSmrg _eglSetConfigKey(&base, key, value); 53901e04c3fSmrg break; 540cdc920a0Smrg } 541cdc920a0Smrg } 542cdc920a0Smrg 5433464ebd5Sriastradh if (attr_list) 54401e04c3fSmrg for (int i = 0; attr_list[i] != EGL_NONE; i += 2) 5453464ebd5Sriastradh _eglSetConfigKey(&base, attr_list[i], attr_list[i+1]); 546cdc920a0Smrg 5477ec681f3Smrg if (rgba_shifts && memcmp(rgba_shifts, dri_shifts, sizeof(dri_shifts))) 5487ec681f3Smrg return NULL; 5497ec681f3Smrg 5507ec681f3Smrg if (rgba_sizes && memcmp(rgba_sizes, dri_sizes, sizeof(dri_sizes))) 5513464ebd5Sriastradh return NULL; 552cdc920a0Smrg 5533464ebd5Sriastradh base.NativeRenderable = EGL_TRUE; 554cdc920a0Smrg 5553464ebd5Sriastradh base.SurfaceType = surface_type; 5563464ebd5Sriastradh if (surface_type & (EGL_PBUFFER_BIT | 5573464ebd5Sriastradh (disp->Extensions.NOK_texture_from_pixmap ? EGL_PIXMAP_BIT : 0))) { 5583464ebd5Sriastradh base.BindToTextureRGB = bind_to_texture_rgb; 5593464ebd5Sriastradh if (base.AlphaSize > 0) 5603464ebd5Sriastradh base.BindToTextureRGBA = bind_to_texture_rgba; 561cdc920a0Smrg } 562cdc920a0Smrg 5637ec681f3Smrg if (double_buffer) { 5647ec681f3Smrg surface_type &= ~EGL_PIXMAP_BIT; 5657ec681f3Smrg } 5667ec681f3Smrg 5677ec681f3Smrg if (!surface_type) 5687ec681f3Smrg return NULL; 5697ec681f3Smrg 5703464ebd5Sriastradh base.RenderableType = disp->ClientAPIs; 5713464ebd5Sriastradh base.Conformant = disp->ClientAPIs; 572cdc920a0Smrg 573af69d88dSmrg base.MinSwapInterval = dri2_dpy->min_swap_interval; 574af69d88dSmrg base.MaxSwapInterval = dri2_dpy->max_swap_interval; 575af69d88dSmrg 576cdc920a0Smrg if (!_eglValidateConfig(&base, EGL_FALSE)) { 577cdc920a0Smrg _eglLog(_EGL_DEBUG, "DRI2: failed to validate config %d", id); 5783464ebd5Sriastradh return NULL; 579cdc920a0Smrg } 580cdc920a0Smrg 5813464ebd5Sriastradh config_id = base.ConfigID; 5823464ebd5Sriastradh base.ConfigID = EGL_DONT_CARE; 5833464ebd5Sriastradh base.SurfaceType = EGL_DONT_CARE; 5843464ebd5Sriastradh num_configs = _eglFilterArray(disp->Configs, (void **) &matching_config, 1, 5853464ebd5Sriastradh (_EGLArrayForEach) dri2_match_config, &base); 5863464ebd5Sriastradh 5873464ebd5Sriastradh if (num_configs == 1) { 5883464ebd5Sriastradh conf = (struct dri2_egl_config *) matching_config; 5893464ebd5Sriastradh 59001e04c3fSmrg if (!conf->dri_config[double_buffer][srgb]) 59101e04c3fSmrg conf->dri_config[double_buffer][srgb] = dri_config; 5923464ebd5Sriastradh else 5933464ebd5Sriastradh /* a similar config type is already added (unlikely) => discard */ 5943464ebd5Sriastradh return NULL; 595cdc920a0Smrg } 5963464ebd5Sriastradh else if (num_configs == 0) { 59701e04c3fSmrg conf = calloc(1, sizeof *conf); 5983464ebd5Sriastradh if (conf == NULL) 5993464ebd5Sriastradh return NULL; 600cdc920a0Smrg 60101e04c3fSmrg conf->dri_config[double_buffer][srgb] = dri_config; 60201e04c3fSmrg 6033464ebd5Sriastradh memcpy(&conf->base, &base, sizeof base); 6043464ebd5Sriastradh conf->base.SurfaceType = 0; 6053464ebd5Sriastradh conf->base.ConfigID = config_id; 606cdc920a0Smrg 6073464ebd5Sriastradh _eglLinkConfig(&conf->base); 608cdc920a0Smrg } 6093464ebd5Sriastradh else { 61001e04c3fSmrg unreachable("duplicates should not be possible"); 611cdc920a0Smrg return NULL; 6123464ebd5Sriastradh } 613cdc920a0Smrg 6147ec681f3Smrg conf->base.SurfaceType |= surface_type; 615af69d88dSmrg 6167ec681f3Smrg return conf; 6177ec681f3Smrg} 6187ec681f3Smrg 6197ec681f3SmrgEGLBoolean 6207ec681f3Smrgdri2_add_pbuffer_configs_for_visuals(_EGLDisplay *disp) 6217ec681f3Smrg{ 6227ec681f3Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 6237ec681f3Smrg unsigned int format_count[ARRAY_SIZE(dri2_pbuffer_visuals)] = { 0 }; 6247ec681f3Smrg unsigned int config_count = 0; 6257ec681f3Smrg 6267ec681f3Smrg for (unsigned i = 0; dri2_dpy->driver_configs[i] != NULL; i++) { 6277ec681f3Smrg for (unsigned j = 0; j < ARRAY_SIZE(dri2_pbuffer_visuals); j++) { 6287ec681f3Smrg struct dri2_egl_config *dri2_conf; 6297ec681f3Smrg 6307ec681f3Smrg dri2_conf = dri2_add_config(disp, dri2_dpy->driver_configs[i], 6317ec681f3Smrg config_count + 1, EGL_PBUFFER_BIT, NULL, 6327ec681f3Smrg dri2_pbuffer_visuals[j].rgba_shifts, dri2_pbuffer_visuals[j].rgba_sizes); 6337ec681f3Smrg 6347ec681f3Smrg if (dri2_conf) { 6357ec681f3Smrg if (dri2_conf->base.ConfigID == config_count + 1) 6367ec681f3Smrg config_count++; 6377ec681f3Smrg format_count[j]++; 6387ec681f3Smrg } 6397ec681f3Smrg } 64001e04c3fSmrg } 64101e04c3fSmrg 6427ec681f3Smrg for (unsigned i = 0; i < ARRAY_SIZE(format_count); i++) { 6437ec681f3Smrg if (!format_count[i]) { 6447ec681f3Smrg _eglLog(_EGL_DEBUG, "No DRI config supports native format %s", 6457ec681f3Smrg dri2_pbuffer_visuals[i].format_name); 6467ec681f3Smrg } 6477ec681f3Smrg } 648cdc920a0Smrg 6497ec681f3Smrg return (config_count != 0); 650cdc920a0Smrg} 651cdc920a0Smrg 6527ec681f3SmrgGLboolean 6537ec681f3Smrgdri2_validate_egl_image(void *image, void *data) 654cdc920a0Smrg{ 6553464ebd5Sriastradh _EGLDisplay *disp = data; 656cdc920a0Smrg _EGLImage *img; 657cdc920a0Smrg 6587ec681f3Smrg mtx_lock(&disp->Mutex); 659cdc920a0Smrg img = _eglLookupImage(image, disp); 6607ec681f3Smrg mtx_unlock(&disp->Mutex); 6617ec681f3Smrg 662cdc920a0Smrg if (img == NULL) { 6637ec681f3Smrg _eglError(EGL_BAD_PARAMETER, "dri2_validate_egl_image"); 6647ec681f3Smrg return false; 665cdc920a0Smrg } 666cdc920a0Smrg 6677ec681f3Smrg return true; 6687ec681f3Smrg} 6697ec681f3Smrg 6707ec681f3Smrg__DRIimage * 6717ec681f3Smrgdri2_lookup_egl_image_validated(void *image, void *data) 6727ec681f3Smrg{ 6737ec681f3Smrg struct dri2_egl_image *dri2_img; 6747ec681f3Smrg 6757ec681f3Smrg (void)data; 6767ec681f3Smrg 677cdc920a0Smrg dri2_img = dri2_egl_image(image); 678cdc920a0Smrg 679cdc920a0Smrg return dri2_img->dri_image; 680cdc920a0Smrg} 681cdc920a0Smrg 6827ec681f3Smrg__DRIimage * 6837ec681f3Smrgdri2_lookup_egl_image(__DRIscreen *screen, void *image, void *data) 6847ec681f3Smrg{ 6857ec681f3Smrg (void) screen; 6867ec681f3Smrg 6877ec681f3Smrg if (!dri2_validate_egl_image(image, data)) 6887ec681f3Smrg return NULL; 6897ec681f3Smrg 6907ec681f3Smrg return dri2_lookup_egl_image_validated(image, data); 6917ec681f3Smrg} 6927ec681f3Smrg 6933464ebd5Sriastradhconst __DRIimageLookupExtension image_lookup_extension = { 6947ec681f3Smrg .base = { __DRI_IMAGE_LOOKUP, 2 }, 695cdc920a0Smrg 6967ec681f3Smrg .lookupEGLImage = dri2_lookup_egl_image, 6977ec681f3Smrg .validateEGLImage = dri2_validate_egl_image, 6987ec681f3Smrg .lookupEGLImageValidated = dri2_lookup_egl_image_validated, 699af69d88dSmrg}; 700cdc920a0Smrg 701cdc920a0Smrgstruct dri2_extension_match { 702cdc920a0Smrg const char *name; 703cdc920a0Smrg int version; 704cdc920a0Smrg int offset; 705cdc920a0Smrg}; 706cdc920a0Smrg 70701e04c3fSmrgstatic const struct dri2_extension_match dri3_driver_extensions[] = { 70801e04c3fSmrg { __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) }, 70901e04c3fSmrg { __DRI_IMAGE_DRIVER, 1, offsetof(struct dri2_egl_display, image_driver) }, 71001e04c3fSmrg { NULL, 0, 0 } 71101e04c3fSmrg}; 71201e04c3fSmrg 71301e04c3fSmrgstatic const struct dri2_extension_match dri2_driver_extensions[] = { 714cdc920a0Smrg { __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) }, 715af69d88dSmrg { __DRI_DRI2, 2, offsetof(struct dri2_egl_display, dri2) }, 7163464ebd5Sriastradh { NULL, 0, 0 } 717cdc920a0Smrg}; 718cdc920a0Smrg 71901e04c3fSmrgstatic const struct dri2_extension_match dri2_core_extensions[] = { 720cdc920a0Smrg { __DRI2_FLUSH, 1, offsetof(struct dri2_egl_display, flush) }, 721cdc920a0Smrg { __DRI_TEX_BUFFER, 2, offsetof(struct dri2_egl_display, tex_buffer) }, 722cdc920a0Smrg { __DRI_IMAGE, 1, offsetof(struct dri2_egl_display, image) }, 7233464ebd5Sriastradh { NULL, 0, 0 } 7243464ebd5Sriastradh}; 7253464ebd5Sriastradh 72601e04c3fSmrgstatic const struct dri2_extension_match swrast_driver_extensions[] = { 7273464ebd5Sriastradh { __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) }, 7283464ebd5Sriastradh { __DRI_SWRAST, 2, offsetof(struct dri2_egl_display, swrast) }, 729af69d88dSmrg { NULL, 0, 0 } 7303464ebd5Sriastradh}; 7313464ebd5Sriastradh 73201e04c3fSmrgstatic const struct dri2_extension_match swrast_core_extensions[] = { 7333464ebd5Sriastradh { __DRI_TEX_BUFFER, 2, offsetof(struct dri2_egl_display, tex_buffer) }, 734af69d88dSmrg { NULL, 0, 0 } 735cdc920a0Smrg}; 736cdc920a0Smrg 7377e102996Smayastatic const struct dri2_extension_match optional_driver_extensions[] = { 7387e102996Smaya { __DRI_CONFIG_OPTIONS, 1, offsetof(struct dri2_egl_display, configOptions) }, 7397e102996Smaya { NULL, 0, 0 } 7407e102996Smaya}; 7417e102996Smaya 74201e04c3fSmrgstatic const struct dri2_extension_match optional_core_extensions[] = { 74301e04c3fSmrg { __DRI2_ROBUSTNESS, 1, offsetof(struct dri2_egl_display, robustness) }, 74401e04c3fSmrg { __DRI2_NO_ERROR, 1, offsetof(struct dri2_egl_display, no_error) }, 74501e04c3fSmrg { __DRI2_CONFIG_QUERY, 1, offsetof(struct dri2_egl_display, config) }, 74601e04c3fSmrg { __DRI2_FENCE, 1, offsetof(struct dri2_egl_display, fence) }, 7477ec681f3Smrg { __DRI2_BUFFER_DAMAGE, 1, offsetof(struct dri2_egl_display, buffer_damage) }, 74801e04c3fSmrg { __DRI2_RENDERER_QUERY, 1, offsetof(struct dri2_egl_display, rendererQuery) }, 74901e04c3fSmrg { __DRI2_INTEROP, 1, offsetof(struct dri2_egl_display, interop) }, 75001e04c3fSmrg { __DRI_IMAGE, 1, offsetof(struct dri2_egl_display, image) }, 75101e04c3fSmrg { __DRI2_FLUSH_CONTROL, 1, offsetof(struct dri2_egl_display, flush_control) }, 75201e04c3fSmrg { __DRI2_BLOB, 1, offsetof(struct dri2_egl_display, blob) }, 75301e04c3fSmrg { __DRI_MUTABLE_RENDER_BUFFER_DRIVER, 1, offsetof(struct dri2_egl_display, mutable_render_buffer) }, 75401e04c3fSmrg { NULL, 0, 0 } 75501e04c3fSmrg}; 75601e04c3fSmrg 757cdc920a0Smrgstatic EGLBoolean 758cdc920a0Smrgdri2_bind_extensions(struct dri2_egl_display *dri2_dpy, 75901e04c3fSmrg const struct dri2_extension_match *matches, 76001e04c3fSmrg const __DRIextension **extensions, 76101e04c3fSmrg bool optional) 762cdc920a0Smrg{ 76301e04c3fSmrg int ret = EGL_TRUE; 764cdc920a0Smrg void *field; 765cdc920a0Smrg 76601e04c3fSmrg for (int i = 0; extensions[i]; i++) { 76701e04c3fSmrg _eglLog(_EGL_DEBUG, "found extension `%s'", extensions[i]->name); 76801e04c3fSmrg for (int j = 0; matches[j].name; j++) { 76901e04c3fSmrg if (strcmp(extensions[i]->name, matches[j].name) == 0 && 77001e04c3fSmrg extensions[i]->version >= matches[j].version) { 77101e04c3fSmrg field = ((char *) dri2_dpy + matches[j].offset); 77201e04c3fSmrg *(const __DRIextension **) field = extensions[i]; 77301e04c3fSmrg _eglLog(_EGL_INFO, "found extension %s version %d", 77401e04c3fSmrg extensions[i]->name, extensions[i]->version); 77501e04c3fSmrg break; 77601e04c3fSmrg } 777cdc920a0Smrg } 778cdc920a0Smrg } 77901e04c3fSmrg 78001e04c3fSmrg for (int j = 0; matches[j].name; j++) { 781cdc920a0Smrg field = ((char *) dri2_dpy + matches[j].offset); 782cdc920a0Smrg if (*(const __DRIextension **) field == NULL) { 78301e04c3fSmrg if (optional) { 78401e04c3fSmrg _eglLog(_EGL_DEBUG, "did not find optional extension %s version %d", 78501e04c3fSmrg matches[j].name, matches[j].version); 78601e04c3fSmrg } else { 78701e04c3fSmrg _eglLog(_EGL_WARNING, "did not find extension %s version %d", 78801e04c3fSmrg matches[j].name, matches[j].version); 78901e04c3fSmrg ret = EGL_FALSE; 79001e04c3fSmrg } 791cdc920a0Smrg } 792cdc920a0Smrg } 793cdc920a0Smrg 794cdc920a0Smrg return ret; 795cdc920a0Smrg} 796cdc920a0Smrg 7973464ebd5Sriastradhstatic const __DRIextension ** 7983464ebd5Sriastradhdri2_open_driver(_EGLDisplay *disp) 799cdc920a0Smrg{ 80001e04c3fSmrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 8017e102996Smaya static const char *search_path_vars[] = { 8027e102996Smaya "LIBGL_DRIVERS_PATH", 8037e102996Smaya NULL, 8047e102996Smaya }; 805cdc920a0Smrg 8067e102996Smaya return loader_open_driver(dri2_dpy->driver_name, 8077e102996Smaya &dri2_dpy->driver, 8087e102996Smaya search_path_vars); 809cdc920a0Smrg} 810cdc920a0Smrg 8117e102996Smayastatic EGLBoolean 8127e102996Smayadri2_load_driver_common(_EGLDisplay *disp, 8137e102996Smaya const struct dri2_extension_match *driver_extensions) 81401e04c3fSmrg{ 81501e04c3fSmrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 81601e04c3fSmrg const __DRIextension **extensions; 81701e04c3fSmrg 81801e04c3fSmrg extensions = dri2_open_driver(disp); 81901e04c3fSmrg if (!extensions) 82001e04c3fSmrg return EGL_FALSE; 82101e04c3fSmrg 8227e102996Smaya if (!dri2_bind_extensions(dri2_dpy, driver_extensions, extensions, false)) { 82301e04c3fSmrg dlclose(dri2_dpy->driver); 8247ec681f3Smrg dri2_dpy->driver = NULL; 82501e04c3fSmrg return EGL_FALSE; 82601e04c3fSmrg } 82701e04c3fSmrg dri2_dpy->driver_extensions = extensions; 82801e04c3fSmrg 8297e102996Smaya dri2_bind_extensions(dri2_dpy, optional_driver_extensions, extensions, true); 8307e102996Smaya 83101e04c3fSmrg return EGL_TRUE; 83201e04c3fSmrg} 83301e04c3fSmrg 8343464ebd5SriastradhEGLBoolean 8353464ebd5Sriastradhdri2_load_driver(_EGLDisplay *disp) 836cdc920a0Smrg{ 8377e102996Smaya return dri2_load_driver_common(disp, dri2_driver_extensions); 8387e102996Smaya} 839cdc920a0Smrg 8407e102996SmayaEGLBoolean 8417e102996Smayadri2_load_driver_dri3(_EGLDisplay *disp) 8427e102996Smaya{ 8437e102996Smaya return dri2_load_driver_common(disp, dri3_driver_extensions); 844cdc920a0Smrg} 845cdc920a0Smrg 8463464ebd5SriastradhEGLBoolean 8473464ebd5Sriastradhdri2_load_driver_swrast(_EGLDisplay *disp) 848cdc920a0Smrg{ 8497e102996Smaya return dri2_load_driver_common(disp, swrast_driver_extensions); 850cdc920a0Smrg} 851cdc920a0Smrg 85201e04c3fSmrgstatic unsigned 85301e04c3fSmrgdri2_renderer_query_integer(struct dri2_egl_display *dri2_dpy, int param) 85401e04c3fSmrg{ 85501e04c3fSmrg const __DRI2rendererQueryExtension *rendererQuery = dri2_dpy->rendererQuery; 85601e04c3fSmrg unsigned int value = 0; 85701e04c3fSmrg 85801e04c3fSmrg if (!rendererQuery || 85901e04c3fSmrg rendererQuery->queryInteger(dri2_dpy->dri_screen, param, &value) == -1) 86001e04c3fSmrg return 0; 86101e04c3fSmrg 86201e04c3fSmrg return value; 86301e04c3fSmrg} 86401e04c3fSmrg 8657e102996Smayastatic const char * 8667e102996Smayadri2_query_driver_name(_EGLDisplay *disp) 8677e102996Smaya{ 8687e102996Smaya struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 8697e102996Smaya return dri2_dpy->driver_name; 8707e102996Smaya} 8717e102996Smaya 8727e102996Smayastatic char * 8737e102996Smayadri2_query_driver_config(_EGLDisplay *disp) 8747e102996Smaya{ 8757e102996Smaya struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 8767e102996Smaya const __DRIconfigOptionsExtension *ext = dri2_dpy->configOptions; 8777e102996Smaya 8787e102996Smaya if (ext->base.version >= 2) 8797e102996Smaya return ext->getXml(dri2_dpy->driver_name); 8807e102996Smaya 8817e102996Smaya return strdup(ext->xml); 8827e102996Smaya} 8837e102996Smaya 8847e102996Smaya 8853464ebd5Sriastradhvoid 8863464ebd5Sriastradhdri2_setup_screen(_EGLDisplay *disp) 887cdc920a0Smrg{ 8883464ebd5Sriastradh struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 8893464ebd5Sriastradh unsigned int api_mask; 890cdc920a0Smrg 89101e04c3fSmrg /* 89201e04c3fSmrg * EGL 1.5 specification defines the default value to 1. Moreover, 89301e04c3fSmrg * eglSwapInterval() is required to clamp requested value to the supported 89401e04c3fSmrg * range. Since the default value is implicitly assumed to be supported, 89501e04c3fSmrg * use it as both minimum and maximum for the platforms that do not allow 89601e04c3fSmrg * changing the interval. Platforms, which allow it (e.g. x11, wayland) 89701e04c3fSmrg * override these values already. 89801e04c3fSmrg */ 89901e04c3fSmrg dri2_dpy->min_swap_interval = 1; 90001e04c3fSmrg dri2_dpy->max_swap_interval = 1; 90101e04c3fSmrg dri2_dpy->default_swap_interval = 1; 90201e04c3fSmrg 90301e04c3fSmrg if (dri2_dpy->image_driver) { 90401e04c3fSmrg api_mask = dri2_dpy->image_driver->getAPIMask(dri2_dpy->dri_screen); 90501e04c3fSmrg } else if (dri2_dpy->dri2) { 906af69d88dSmrg api_mask = dri2_dpy->dri2->getAPIMask(dri2_dpy->dri_screen); 907cdc920a0Smrg } else { 9083464ebd5Sriastradh assert(dri2_dpy->swrast); 909af69d88dSmrg api_mask = 1 << __DRI_API_OPENGL | 910af69d88dSmrg 1 << __DRI_API_GLES | 911af69d88dSmrg 1 << __DRI_API_GLES2 | 912af69d88dSmrg 1 << __DRI_API_GLES3; 913cdc920a0Smrg } 914cdc920a0Smrg 9153464ebd5Sriastradh disp->ClientAPIs = 0; 91601e04c3fSmrg if ((api_mask & (1 <<__DRI_API_OPENGL)) && _eglIsApiValid(EGL_OPENGL_API)) 9173464ebd5Sriastradh disp->ClientAPIs |= EGL_OPENGL_BIT; 91801e04c3fSmrg if ((api_mask & (1 << __DRI_API_GLES)) && _eglIsApiValid(EGL_OPENGL_ES_API)) 9193464ebd5Sriastradh disp->ClientAPIs |= EGL_OPENGL_ES_BIT; 92001e04c3fSmrg if ((api_mask & (1 << __DRI_API_GLES2)) && _eglIsApiValid(EGL_OPENGL_ES_API)) 9213464ebd5Sriastradh disp->ClientAPIs |= EGL_OPENGL_ES2_BIT; 92201e04c3fSmrg if ((api_mask & (1 << __DRI_API_GLES3)) && _eglIsApiValid(EGL_OPENGL_ES_API)) 923af69d88dSmrg disp->ClientAPIs |= EGL_OPENGL_ES3_BIT_KHR; 9243464ebd5Sriastradh 92501e04c3fSmrg assert(dri2_dpy->image_driver || dri2_dpy->dri2 || dri2_dpy->swrast); 92601e04c3fSmrg disp->Extensions.KHR_no_config_context = EGL_TRUE; 927af69d88dSmrg disp->Extensions.KHR_surfaceless_context = EGL_TRUE; 928af69d88dSmrg 9297e102996Smaya if (dri2_dpy->configOptions) { 9307e102996Smaya disp->Extensions.MESA_query_driver = EGL_TRUE; 9317e102996Smaya } 9327e102996Smaya 93301e04c3fSmrg /* Report back to EGL the bitmask of priorities supported */ 93401e04c3fSmrg disp->Extensions.IMG_context_priority = 93501e04c3fSmrg dri2_renderer_query_integer(dri2_dpy, 93601e04c3fSmrg __DRI2_RENDERER_HAS_CONTEXT_PRIORITY); 93701e04c3fSmrg 93801e04c3fSmrg disp->Extensions.EXT_pixel_format_float = EGL_TRUE; 93901e04c3fSmrg 94001e04c3fSmrg if (dri2_renderer_query_integer(dri2_dpy, 94101e04c3fSmrg __DRI2_RENDERER_HAS_FRAMEBUFFER_SRGB)) 94201e04c3fSmrg disp->Extensions.KHR_gl_colorspace = EGL_TRUE; 94301e04c3fSmrg 94401e04c3fSmrg if (dri2_dpy->image_driver || 94501e04c3fSmrg (dri2_dpy->dri2 && dri2_dpy->dri2->base.version >= 3) || 94601e04c3fSmrg (dri2_dpy->swrast && dri2_dpy->swrast->base.version >= 3)) { 947af69d88dSmrg disp->Extensions.KHR_create_context = EGL_TRUE; 948af69d88dSmrg 949af69d88dSmrg if (dri2_dpy->robustness) 950af69d88dSmrg disp->Extensions.EXT_create_context_robustness = EGL_TRUE; 951cdc920a0Smrg } 952cdc920a0Smrg 95301e04c3fSmrg if (dri2_dpy->no_error) 95401e04c3fSmrg disp->Extensions.KHR_create_context_no_error = EGL_TRUE; 95501e04c3fSmrg 95601e04c3fSmrg if (dri2_dpy->fence) { 95701e04c3fSmrg disp->Extensions.KHR_fence_sync = EGL_TRUE; 95801e04c3fSmrg disp->Extensions.KHR_wait_sync = EGL_TRUE; 95901e04c3fSmrg if (dri2_dpy->fence->get_fence_from_cl_event) 96001e04c3fSmrg disp->Extensions.KHR_cl_event2 = EGL_TRUE; 96101e04c3fSmrg if (dri2_dpy->fence->base.version >= 2 && 96201e04c3fSmrg dri2_dpy->fence->get_capabilities) { 96301e04c3fSmrg unsigned capabilities = 96401e04c3fSmrg dri2_dpy->fence->get_capabilities(dri2_dpy->dri_screen); 96501e04c3fSmrg disp->Extensions.ANDROID_native_fence_sync = 96601e04c3fSmrg (capabilities & __DRI_FENCE_CAP_NATIVE_FD) != 0; 96701e04c3fSmrg } 96801e04c3fSmrg } 96901e04c3fSmrg 97001e04c3fSmrg if (dri2_dpy->blob) 97101e04c3fSmrg disp->Extensions.ANDROID_blob_cache = EGL_TRUE; 97201e04c3fSmrg 97301e04c3fSmrg disp->Extensions.KHR_reusable_sync = EGL_TRUE; 97401e04c3fSmrg 9753464ebd5Sriastradh if (dri2_dpy->image) { 976af69d88dSmrg if (dri2_dpy->image->base.version >= 10 && 977af69d88dSmrg dri2_dpy->image->getCapabilities != NULL) { 978af69d88dSmrg int capabilities; 979af69d88dSmrg 980af69d88dSmrg capabilities = dri2_dpy->image->getCapabilities(dri2_dpy->dri_screen); 981af69d88dSmrg disp->Extensions.MESA_drm_image = (capabilities & __DRI_IMAGE_CAP_GLOBAL_NAMES) != 0; 98201e04c3fSmrg 98301e04c3fSmrg if (dri2_dpy->image->base.version >= 11) 98401e04c3fSmrg disp->Extensions.MESA_image_dma_buf_export = EGL_TRUE; 98501e04c3fSmrg } else { 986af69d88dSmrg disp->Extensions.MESA_drm_image = EGL_TRUE; 98701e04c3fSmrg if (dri2_dpy->image->base.version >= 11) 98801e04c3fSmrg disp->Extensions.MESA_image_dma_buf_export = EGL_TRUE; 98901e04c3fSmrg } 990af69d88dSmrg 9913464ebd5Sriastradh disp->Extensions.KHR_image_base = EGL_TRUE; 9923464ebd5Sriastradh disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE; 993af69d88dSmrg if (dri2_dpy->image->base.version >= 5 && 994af69d88dSmrg dri2_dpy->image->createImageFromTexture) { 995af69d88dSmrg disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE; 996af69d88dSmrg disp->Extensions.KHR_gl_texture_cubemap_image = EGL_TRUE; 99701e04c3fSmrg 99801e04c3fSmrg if (dri2_renderer_query_integer(dri2_dpy, 99901e04c3fSmrg __DRI2_RENDERER_HAS_TEXTURE_3D)) 100001e04c3fSmrg disp->Extensions.KHR_gl_texture_3D_image = EGL_TRUE; 1001af69d88dSmrg } 100201e04c3fSmrg#ifdef HAVE_LIBDRM 1003af69d88dSmrg if (dri2_dpy->image->base.version >= 8 && 1004af69d88dSmrg dri2_dpy->image->createImageFromDmaBufs) { 1005af69d88dSmrg disp->Extensions.EXT_image_dma_buf_import = EGL_TRUE; 100601e04c3fSmrg disp->Extensions.EXT_image_dma_buf_import_modifiers = EGL_TRUE; 100701e04c3fSmrg } 1008af69d88dSmrg#endif 1009cdc920a0Smrg } 101001e04c3fSmrg 101101e04c3fSmrg if (dri2_dpy->flush_control) 101201e04c3fSmrg disp->Extensions.KHR_context_flush_control = EGL_TRUE; 10137ec681f3Smrg 10147ec681f3Smrg if (dri2_dpy->buffer_damage && dri2_dpy->buffer_damage->set_damage_region) 10157ec681f3Smrg disp->Extensions.KHR_partial_update = EGL_TRUE; 10167ec681f3Smrg 10177ec681f3Smrg disp->Extensions.EXT_protected_surface = 10187ec681f3Smrg dri2_renderer_query_integer(dri2_dpy, 10197ec681f3Smrg __DRI2_RENDERER_HAS_PROTECTED_CONTENT); 102001e04c3fSmrg} 102101e04c3fSmrg 102201e04c3fSmrgvoid 102301e04c3fSmrgdri2_setup_swap_interval(_EGLDisplay *disp, int max_swap_interval) 102401e04c3fSmrg{ 102501e04c3fSmrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 102601e04c3fSmrg GLint vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1; 102701e04c3fSmrg 102801e04c3fSmrg /* Allow driconf to override applications.*/ 102901e04c3fSmrg if (dri2_dpy->config) 103001e04c3fSmrg dri2_dpy->config->configQueryi(dri2_dpy->dri_screen, 103101e04c3fSmrg "vblank_mode", &vblank_mode); 103201e04c3fSmrg switch (vblank_mode) { 103301e04c3fSmrg case DRI_CONF_VBLANK_NEVER: 103401e04c3fSmrg dri2_dpy->min_swap_interval = 0; 103501e04c3fSmrg dri2_dpy->max_swap_interval = 0; 103601e04c3fSmrg dri2_dpy->default_swap_interval = 0; 103701e04c3fSmrg break; 103801e04c3fSmrg case DRI_CONF_VBLANK_ALWAYS_SYNC: 103901e04c3fSmrg dri2_dpy->min_swap_interval = 1; 104001e04c3fSmrg dri2_dpy->max_swap_interval = max_swap_interval; 104101e04c3fSmrg dri2_dpy->default_swap_interval = 1; 104201e04c3fSmrg break; 104301e04c3fSmrg case DRI_CONF_VBLANK_DEF_INTERVAL_0: 104401e04c3fSmrg dri2_dpy->min_swap_interval = 0; 104501e04c3fSmrg dri2_dpy->max_swap_interval = max_swap_interval; 104601e04c3fSmrg dri2_dpy->default_swap_interval = 0; 104701e04c3fSmrg break; 104801e04c3fSmrg default: 104901e04c3fSmrg case DRI_CONF_VBLANK_DEF_INTERVAL_1: 105001e04c3fSmrg dri2_dpy->min_swap_interval = 0; 105101e04c3fSmrg dri2_dpy->max_swap_interval = max_swap_interval; 105201e04c3fSmrg dri2_dpy->default_swap_interval = 1; 105301e04c3fSmrg break; 105401e04c3fSmrg } 10553464ebd5Sriastradh} 1056cdc920a0Smrg 105701e04c3fSmrg/* All platforms but DRM call this function to create the screen and populate 105801e04c3fSmrg * the driver_configs. DRM inherits that information from its display - GBM. 105901e04c3fSmrg */ 10603464ebd5SriastradhEGLBoolean 10613464ebd5Sriastradhdri2_create_screen(_EGLDisplay *disp) 10623464ebd5Sriastradh{ 106301e04c3fSmrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1064cdc920a0Smrg 106501e04c3fSmrg if (dri2_dpy->image_driver) { 106601e04c3fSmrg dri2_dpy->dri_screen = 106701e04c3fSmrg dri2_dpy->image_driver->createNewScreen2(0, dri2_dpy->fd, 106801e04c3fSmrg dri2_dpy->loader_extensions, 106901e04c3fSmrg dri2_dpy->driver_extensions, 107001e04c3fSmrg &dri2_dpy->driver_configs, 107101e04c3fSmrg disp); 107201e04c3fSmrg } else if (dri2_dpy->dri2) { 1073af69d88dSmrg if (dri2_dpy->dri2->base.version >= 4) { 1074af69d88dSmrg dri2_dpy->dri_screen = 1075af69d88dSmrg dri2_dpy->dri2->createNewScreen2(0, dri2_dpy->fd, 107601e04c3fSmrg dri2_dpy->loader_extensions, 1077af69d88dSmrg dri2_dpy->driver_extensions, 1078af69d88dSmrg &dri2_dpy->driver_configs, disp); 1079af69d88dSmrg } else { 1080af69d88dSmrg dri2_dpy->dri_screen = 1081af69d88dSmrg dri2_dpy->dri2->createNewScreen(0, dri2_dpy->fd, 108201e04c3fSmrg dri2_dpy->loader_extensions, 1083af69d88dSmrg &dri2_dpy->driver_configs, disp); 1084af69d88dSmrg } 1085cdc920a0Smrg } else { 10863464ebd5Sriastradh assert(dri2_dpy->swrast); 1087af69d88dSmrg if (dri2_dpy->swrast->base.version >= 4) { 1088af69d88dSmrg dri2_dpy->dri_screen = 108901e04c3fSmrg dri2_dpy->swrast->createNewScreen2(0, dri2_dpy->loader_extensions, 1090af69d88dSmrg dri2_dpy->driver_extensions, 1091af69d88dSmrg &dri2_dpy->driver_configs, disp); 1092af69d88dSmrg } else { 1093af69d88dSmrg dri2_dpy->dri_screen = 109401e04c3fSmrg dri2_dpy->swrast->createNewScreen(0, dri2_dpy->loader_extensions, 1095af69d88dSmrg &dri2_dpy->driver_configs, disp); 1096af69d88dSmrg } 1097cdc920a0Smrg } 1098cdc920a0Smrg 1099cdc920a0Smrg if (dri2_dpy->dri_screen == NULL) { 11003464ebd5Sriastradh _eglLog(_EGL_WARNING, "DRI2: failed to create dri screen"); 11013464ebd5Sriastradh return EGL_FALSE; 1102cdc920a0Smrg } 1103cdc920a0Smrg 110401e04c3fSmrg dri2_dpy->own_dri_screen = true; 110501e04c3fSmrg return EGL_TRUE; 110601e04c3fSmrg} 110701e04c3fSmrg 110801e04c3fSmrgEGLBoolean 110901e04c3fSmrgdri2_setup_extensions(_EGLDisplay *disp) 111001e04c3fSmrg{ 111101e04c3fSmrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 111201e04c3fSmrg const struct dri2_extension_match *mandatory_core_extensions; 111301e04c3fSmrg const __DRIextension **extensions; 1114cdc920a0Smrg 11153464ebd5Sriastradh extensions = dri2_dpy->core->getExtensions(dri2_dpy->dri_screen); 1116cdc920a0Smrg 111701e04c3fSmrg if (dri2_dpy->image_driver || dri2_dpy->dri2) 111801e04c3fSmrg mandatory_core_extensions = dri2_core_extensions; 111901e04c3fSmrg else 112001e04c3fSmrg mandatory_core_extensions = swrast_core_extensions; 1121cdc920a0Smrg 112201e04c3fSmrg if (!dri2_bind_extensions(dri2_dpy, mandatory_core_extensions, extensions, false)) 112301e04c3fSmrg return EGL_FALSE; 1124cdc920a0Smrg 112501e04c3fSmrg#ifdef HAVE_DRI3_MODIFIERS 112601e04c3fSmrg dri2_dpy->multibuffers_available = 112701e04c3fSmrg (dri2_dpy->dri3_major_version > 1 || (dri2_dpy->dri3_major_version == 1 && 112801e04c3fSmrg dri2_dpy->dri3_minor_version >= 2)) && 112901e04c3fSmrg (dri2_dpy->present_major_version > 1 || (dri2_dpy->present_major_version == 1 && 113001e04c3fSmrg dri2_dpy->present_minor_version >= 2)) && 113101e04c3fSmrg (dri2_dpy->image && dri2_dpy->image->base.version >= 15); 113201e04c3fSmrg#endif 1133cdc920a0Smrg 113401e04c3fSmrg dri2_bind_extensions(dri2_dpy, optional_core_extensions, extensions, true); 113501e04c3fSmrg return EGL_TRUE; 1136cdc920a0Smrg} 1137cdc920a0Smrg 11383464ebd5Sriastradh/** 11397ec681f3Smrg * Called via eglInitialize(), drv->Initialize(). 114001e04c3fSmrg * 114101e04c3fSmrg * This must be guaranteed to be called exactly once, even if eglInitialize is 114201e04c3fSmrg * called many times (without a eglTerminate in between). 11433464ebd5Sriastradh */ 11443464ebd5Sriastradhstatic EGLBoolean 11457ec681f3Smrgdri2_initialize(_EGLDisplay *disp) 11463464ebd5Sriastradh{ 114701e04c3fSmrg EGLBoolean ret = EGL_FALSE; 114801e04c3fSmrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 114901e04c3fSmrg 115001e04c3fSmrg /* In the case where the application calls eglMakeCurrent(context1), 115101e04c3fSmrg * eglTerminate, then eglInitialize again (without a call to eglReleaseThread 115201e04c3fSmrg * or eglMakeCurrent(NULL) before that), dri2_dpy structure is still 115301e04c3fSmrg * initialized, as we need it to be able to free context1 correctly. 115401e04c3fSmrg * 115501e04c3fSmrg * It would probably be safest to forcibly release the display with 115601e04c3fSmrg * dri2_display_release, to make sure the display is reinitialized correctly. 115701e04c3fSmrg * However, the EGL spec states that we need to keep a reference to the 115801e04c3fSmrg * current context (so we cannot call dri2_make_current(NULL)), and therefore 115901e04c3fSmrg * we would leak context1 as we would be missing the old display connection 116001e04c3fSmrg * to free it up correctly. 116101e04c3fSmrg */ 116201e04c3fSmrg if (dri2_dpy) { 116301e04c3fSmrg dri2_dpy->ref_count++; 116401e04c3fSmrg return EGL_TRUE; 116501e04c3fSmrg } 11663464ebd5Sriastradh 11677e102996Smaya loader_set_logger(_eglLog); 11687e102996Smaya 11693464ebd5Sriastradh switch (disp->Platform) { 117001e04c3fSmrg case _EGL_PLATFORM_SURFACELESS: 11717ec681f3Smrg ret = dri2_initialize_surfaceless(disp); 11727ec681f3Smrg break; 11737ec681f3Smrg case _EGL_PLATFORM_DEVICE: 11747ec681f3Smrg ret = dri2_initialize_device(disp); 117501e04c3fSmrg break; 11763464ebd5Sriastradh case _EGL_PLATFORM_X11: 11777ec681f3Smrg case _EGL_PLATFORM_XCB: 11787ec681f3Smrg ret = dri2_initialize_x11(disp); 117901e04c3fSmrg break; 11803464ebd5Sriastradh case _EGL_PLATFORM_DRM: 11817ec681f3Smrg ret = dri2_initialize_drm(disp); 118201e04c3fSmrg break; 11833464ebd5Sriastradh case _EGL_PLATFORM_WAYLAND: 11847ec681f3Smrg ret = dri2_initialize_wayland(disp); 118501e04c3fSmrg break; 1186af69d88dSmrg case _EGL_PLATFORM_ANDROID: 11877ec681f3Smrg ret = dri2_initialize_android(disp); 118801e04c3fSmrg break; 11893464ebd5Sriastradh default: 119001e04c3fSmrg unreachable("Callers ensure we cannot get here."); 11913464ebd5Sriastradh return EGL_FALSE; 11923464ebd5Sriastradh } 119301e04c3fSmrg 119401e04c3fSmrg if (!ret) 119501e04c3fSmrg return EGL_FALSE; 119601e04c3fSmrg 119701e04c3fSmrg dri2_dpy = dri2_egl_display(disp); 119801e04c3fSmrg dri2_dpy->ref_count++; 119901e04c3fSmrg 120001e04c3fSmrg return EGL_TRUE; 12013464ebd5Sriastradh} 12023464ebd5Sriastradh 1203cdc920a0Smrg/** 120401e04c3fSmrg * Decrement display reference count, and free up display if necessary. 1205cdc920a0Smrg */ 120601e04c3fSmrgstatic void 120701e04c3fSmrgdri2_display_release(_EGLDisplay *disp) 1208cdc920a0Smrg{ 120901e04c3fSmrg struct dri2_egl_display *dri2_dpy; 121001e04c3fSmrg 121101e04c3fSmrg if (!disp) 121201e04c3fSmrg return; 121301e04c3fSmrg 121401e04c3fSmrg dri2_dpy = dri2_egl_display(disp); 121501e04c3fSmrg 121601e04c3fSmrg assert(dri2_dpy->ref_count > 0); 121701e04c3fSmrg dri2_dpy->ref_count--; 121801e04c3fSmrg 121901e04c3fSmrg if (dri2_dpy->ref_count > 0) 122001e04c3fSmrg return; 1221cdc920a0Smrg 1222cdc920a0Smrg _eglCleanupDisplay(disp); 122301e04c3fSmrg dri2_display_destroy(disp); 122401e04c3fSmrg} 1225cdc920a0Smrg 122601e04c3fSmrgvoid 122701e04c3fSmrgdri2_display_destroy(_EGLDisplay *disp) 122801e04c3fSmrg{ 122901e04c3fSmrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 123001e04c3fSmrg 123101e04c3fSmrg if (dri2_dpy->own_dri_screen) { 123201e04c3fSmrg if (dri2_dpy->vtbl && dri2_dpy->vtbl->close_screen_notify) 123301e04c3fSmrg dri2_dpy->vtbl->close_screen_notify(disp); 12343464ebd5Sriastradh dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen); 123501e04c3fSmrg } 123601e04c3fSmrg if (dri2_dpy->fd >= 0) 12373464ebd5Sriastradh close(dri2_dpy->fd); 12387ec681f3Smrg 12397ec681f3Smrg /* Don't dlclose the driver when building with the address sanitizer, so you 12407ec681f3Smrg * get good symbols from the leak reports. 12417ec681f3Smrg */ 12427ec681f3Smrg#if !BUILT_WITH_ASAN || defined(NDEBUG) 12433464ebd5Sriastradh if (dri2_dpy->driver) 12443464ebd5Sriastradh dlclose(dri2_dpy->driver); 12457ec681f3Smrg#endif 12467ec681f3Smrg 1247af69d88dSmrg free(dri2_dpy->driver_name); 12483464ebd5Sriastradh 124901e04c3fSmrg#ifdef HAVE_WAYLAND_PLATFORM 125001e04c3fSmrg free(dri2_dpy->device_name); 125101e04c3fSmrg#endif 125201e04c3fSmrg 1253af69d88dSmrg switch (disp->Platform) { 1254af69d88dSmrg case _EGL_PLATFORM_X11: 125501e04c3fSmrg dri2_teardown_x11(dri2_dpy); 1256af69d88dSmrg break; 1257af69d88dSmrg case _EGL_PLATFORM_DRM: 125801e04c3fSmrg dri2_teardown_drm(dri2_dpy); 1259af69d88dSmrg break; 1260af69d88dSmrg case _EGL_PLATFORM_WAYLAND: 126101e04c3fSmrg dri2_teardown_wayland(dri2_dpy); 1262af69d88dSmrg break; 1263af69d88dSmrg default: 126401e04c3fSmrg /* TODO: add teardown for other platforms */ 1265af69d88dSmrg break; 12663464ebd5Sriastradh } 12673464ebd5Sriastradh 126801e04c3fSmrg /* The drm platform does not create the screen/driver_configs but reuses 126901e04c3fSmrg * the ones from the gbm device. As such the gbm itself is responsible 127001e04c3fSmrg * for the cleanup. 127101e04c3fSmrg */ 127201e04c3fSmrg if (disp->Platform != _EGL_PLATFORM_DRM && dri2_dpy->driver_configs) { 127301e04c3fSmrg for (unsigned i = 0; dri2_dpy->driver_configs[i]; i++) 127401e04c3fSmrg free((__DRIconfig *) dri2_dpy->driver_configs[i]); 127501e04c3fSmrg free(dri2_dpy->driver_configs); 127601e04c3fSmrg } 1277cdc920a0Smrg free(dri2_dpy); 1278cdc920a0Smrg disp->DriverData = NULL; 127901e04c3fSmrg} 128001e04c3fSmrg 128101e04c3fSmrg__DRIbuffer * 128201e04c3fSmrgdri2_egl_surface_alloc_local_buffer(struct dri2_egl_surface *dri2_surf, 128301e04c3fSmrg unsigned int att, unsigned int format) 128401e04c3fSmrg{ 128501e04c3fSmrg struct dri2_egl_display *dri2_dpy = 128601e04c3fSmrg dri2_egl_display(dri2_surf->base.Resource.Display); 128701e04c3fSmrg 128801e04c3fSmrg if (att >= ARRAY_SIZE(dri2_surf->local_buffers)) 128901e04c3fSmrg return NULL; 129001e04c3fSmrg 129101e04c3fSmrg if (!dri2_surf->local_buffers[att]) { 129201e04c3fSmrg dri2_surf->local_buffers[att] = 129301e04c3fSmrg dri2_dpy->dri2->allocateBuffer(dri2_dpy->dri_screen, att, format, 129401e04c3fSmrg dri2_surf->base.Width, dri2_surf->base.Height); 129501e04c3fSmrg } 129601e04c3fSmrg 129701e04c3fSmrg return dri2_surf->local_buffers[att]; 129801e04c3fSmrg} 129901e04c3fSmrg 130001e04c3fSmrgvoid 130101e04c3fSmrgdri2_egl_surface_free_local_buffers(struct dri2_egl_surface *dri2_surf) 130201e04c3fSmrg{ 130301e04c3fSmrg struct dri2_egl_display *dri2_dpy = 130401e04c3fSmrg dri2_egl_display(dri2_surf->base.Resource.Display); 130501e04c3fSmrg 130601e04c3fSmrg for (int i = 0; i < ARRAY_SIZE(dri2_surf->local_buffers); i++) { 130701e04c3fSmrg if (dri2_surf->local_buffers[i]) { 130801e04c3fSmrg dri2_dpy->dri2->releaseBuffer(dri2_dpy->dri_screen, 130901e04c3fSmrg dri2_surf->local_buffers[i]); 131001e04c3fSmrg dri2_surf->local_buffers[i] = NULL; 131101e04c3fSmrg } 131201e04c3fSmrg } 131301e04c3fSmrg} 131401e04c3fSmrg 131501e04c3fSmrg/** 13167ec681f3Smrg * Called via eglTerminate(), drv->Terminate(). 131701e04c3fSmrg * 131801e04c3fSmrg * This must be guaranteed to be called exactly once, even if eglTerminate is 131901e04c3fSmrg * called many times (without a eglInitialize in between). 132001e04c3fSmrg */ 132101e04c3fSmrgstatic EGLBoolean 13227ec681f3Smrgdri2_terminate(_EGLDisplay *disp) 132301e04c3fSmrg{ 132401e04c3fSmrg /* Release all non-current Context/Surfaces. */ 13257ec681f3Smrg _eglReleaseDisplayResources(disp); 132601e04c3fSmrg 132701e04c3fSmrg dri2_display_release(disp); 1328cdc920a0Smrg 1329cdc920a0Smrg return EGL_TRUE; 1330cdc920a0Smrg} 1331cdc920a0Smrg 1332af69d88dSmrg/** 1333af69d88dSmrg * Set the error code after a call to 1334af69d88dSmrg * dri2_egl_display::dri2::createContextAttribs. 1335af69d88dSmrg */ 1336af69d88dSmrgstatic void 1337af69d88dSmrgdri2_create_context_attribs_error(int dri_error) 1338af69d88dSmrg{ 1339af69d88dSmrg EGLint egl_error; 1340af69d88dSmrg 1341af69d88dSmrg switch (dri_error) { 1342af69d88dSmrg case __DRI_CTX_ERROR_SUCCESS: 1343af69d88dSmrg return; 1344af69d88dSmrg 1345af69d88dSmrg case __DRI_CTX_ERROR_NO_MEMORY: 1346af69d88dSmrg egl_error = EGL_BAD_ALLOC; 1347af69d88dSmrg break; 1348af69d88dSmrg 1349af69d88dSmrg /* From the EGL_KHR_create_context spec, section "Errors": 1350af69d88dSmrg * 1351af69d88dSmrg * * If <config> does not support a client API context compatible 1352af69d88dSmrg * with the requested API major and minor version, [...] context flags, 1353af69d88dSmrg * and context reset notification behavior (for client API types where 1354af69d88dSmrg * these attributes are supported), then an EGL_BAD_MATCH error is 1355af69d88dSmrg * generated. 1356af69d88dSmrg * 1357af69d88dSmrg * * If an OpenGL ES context is requested and the values for 1358af69d88dSmrg * attributes EGL_CONTEXT_MAJOR_VERSION_KHR and 1359af69d88dSmrg * EGL_CONTEXT_MINOR_VERSION_KHR specify an OpenGL ES version that 1360af69d88dSmrg * is not defined, than an EGL_BAD_MATCH error is generated. 1361af69d88dSmrg * 1362af69d88dSmrg * * If an OpenGL context is requested, the requested version is 1363af69d88dSmrg * greater than 3.2, and the value for attribute 1364af69d88dSmrg * EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR has no bits set; has any 1365af69d88dSmrg * bits set other than EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR and 1366af69d88dSmrg * EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; has more than 1367af69d88dSmrg * one of these bits set; or if the implementation does not support 1368af69d88dSmrg * the requested profile, then an EGL_BAD_MATCH error is generated. 1369af69d88dSmrg */ 1370af69d88dSmrg case __DRI_CTX_ERROR_BAD_API: 1371af69d88dSmrg case __DRI_CTX_ERROR_BAD_VERSION: 1372af69d88dSmrg case __DRI_CTX_ERROR_BAD_FLAG: 1373af69d88dSmrg egl_error = EGL_BAD_MATCH; 1374af69d88dSmrg break; 1375af69d88dSmrg 1376af69d88dSmrg /* From the EGL_KHR_create_context spec, section "Errors": 1377af69d88dSmrg * 1378af69d88dSmrg * * If an attribute name or attribute value in <attrib_list> is not 1379af69d88dSmrg * recognized (including unrecognized bits in bitmask attributes), 1380af69d88dSmrg * then an EGL_BAD_ATTRIBUTE error is generated." 1381af69d88dSmrg */ 1382af69d88dSmrg case __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE: 1383af69d88dSmrg case __DRI_CTX_ERROR_UNKNOWN_FLAG: 1384af69d88dSmrg egl_error = EGL_BAD_ATTRIBUTE; 1385af69d88dSmrg break; 1386af69d88dSmrg 1387af69d88dSmrg default: 138801e04c3fSmrg assert(!"unknown dri_error code"); 1389af69d88dSmrg egl_error = EGL_BAD_MATCH; 1390af69d88dSmrg break; 1391af69d88dSmrg } 1392af69d88dSmrg 1393af69d88dSmrg _eglError(egl_error, "dri2_create_context"); 1394af69d88dSmrg} 1395cdc920a0Smrg 139601e04c3fSmrgstatic bool 139701e04c3fSmrgdri2_fill_context_attribs(struct dri2_egl_context *dri2_ctx, 139801e04c3fSmrg struct dri2_egl_display *dri2_dpy, 139901e04c3fSmrg uint32_t *ctx_attribs, 140001e04c3fSmrg unsigned *num_attribs) 1401cdc920a0Smrg{ 140201e04c3fSmrg int pos = 0; 14033464ebd5Sriastradh 140401e04c3fSmrg assert(*num_attribs >= NUM_ATTRIBS); 1405cdc920a0Smrg 140601e04c3fSmrg ctx_attribs[pos++] = __DRI_CTX_ATTRIB_MAJOR_VERSION; 140701e04c3fSmrg ctx_attribs[pos++] = dri2_ctx->base.ClientMajorVersion; 140801e04c3fSmrg ctx_attribs[pos++] = __DRI_CTX_ATTRIB_MINOR_VERSION; 140901e04c3fSmrg ctx_attribs[pos++] = dri2_ctx->base.ClientMinorVersion; 141001e04c3fSmrg 141101e04c3fSmrg if (dri2_ctx->base.Flags != 0 || dri2_ctx->base.NoError) { 141201e04c3fSmrg /* If the implementation doesn't support the __DRI2_ROBUSTNESS 141301e04c3fSmrg * extension, don't even try to send it the robust-access flag. 141401e04c3fSmrg * It may explode. Instead, generate the required EGL error here. 141501e04c3fSmrg */ 141601e04c3fSmrg if ((dri2_ctx->base.Flags & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR) != 0 141701e04c3fSmrg && !dri2_dpy->robustness) { 141801e04c3fSmrg _eglError(EGL_BAD_MATCH, "eglCreateContext"); 141901e04c3fSmrg return false; 142001e04c3fSmrg } 142101e04c3fSmrg 142201e04c3fSmrg ctx_attribs[pos++] = __DRI_CTX_ATTRIB_FLAGS; 142301e04c3fSmrg ctx_attribs[pos++] = dri2_ctx->base.Flags | 142401e04c3fSmrg (dri2_ctx->base.NoError ? __DRI_CTX_FLAG_NO_ERROR : 0); 142501e04c3fSmrg } 142601e04c3fSmrg 142701e04c3fSmrg if (dri2_ctx->base.ResetNotificationStrategy != EGL_NO_RESET_NOTIFICATION_KHR) { 142801e04c3fSmrg /* If the implementation doesn't support the __DRI2_ROBUSTNESS 142901e04c3fSmrg * extension, don't even try to send it a reset strategy. It may 143001e04c3fSmrg * explode. Instead, generate the required EGL error here. 143101e04c3fSmrg */ 143201e04c3fSmrg if (!dri2_dpy->robustness) { 143301e04c3fSmrg _eglError(EGL_BAD_CONFIG, "eglCreateContext"); 143401e04c3fSmrg return false; 143501e04c3fSmrg } 143601e04c3fSmrg 143701e04c3fSmrg ctx_attribs[pos++] = __DRI_CTX_ATTRIB_RESET_STRATEGY; 143801e04c3fSmrg ctx_attribs[pos++] = __DRI_CTX_RESET_LOSE_CONTEXT; 143901e04c3fSmrg } 144001e04c3fSmrg 144101e04c3fSmrg if (dri2_ctx->base.ContextPriority != EGL_CONTEXT_PRIORITY_MEDIUM_IMG) { 144201e04c3fSmrg unsigned val; 144301e04c3fSmrg 144401e04c3fSmrg switch (dri2_ctx->base.ContextPriority) { 144501e04c3fSmrg case EGL_CONTEXT_PRIORITY_HIGH_IMG: 144601e04c3fSmrg val = __DRI_CTX_PRIORITY_HIGH; 144701e04c3fSmrg break; 144801e04c3fSmrg case EGL_CONTEXT_PRIORITY_MEDIUM_IMG: 144901e04c3fSmrg val = __DRI_CTX_PRIORITY_MEDIUM; 145001e04c3fSmrg break; 145101e04c3fSmrg case EGL_CONTEXT_PRIORITY_LOW_IMG: 145201e04c3fSmrg val = __DRI_CTX_PRIORITY_LOW; 145301e04c3fSmrg break; 145401e04c3fSmrg default: 145501e04c3fSmrg _eglError(EGL_BAD_CONFIG, "eglCreateContext"); 145601e04c3fSmrg return false; 145701e04c3fSmrg } 145801e04c3fSmrg 145901e04c3fSmrg ctx_attribs[pos++] = __DRI_CTX_ATTRIB_PRIORITY; 146001e04c3fSmrg ctx_attribs[pos++] = val; 146101e04c3fSmrg } 146201e04c3fSmrg 146301e04c3fSmrg if (dri2_ctx->base.ReleaseBehavior == EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR) { 146401e04c3fSmrg ctx_attribs[pos++] = __DRI_CTX_ATTRIB_RELEASE_BEHAVIOR; 146501e04c3fSmrg ctx_attribs[pos++] = __DRI_CTX_RELEASE_BEHAVIOR_NONE; 146601e04c3fSmrg } 146701e04c3fSmrg 146801e04c3fSmrg *num_attribs = pos; 146901e04c3fSmrg 147001e04c3fSmrg return true; 147101e04c3fSmrg} 147201e04c3fSmrg 147301e04c3fSmrg/** 14747ec681f3Smrg * Called via eglCreateContext(), drv->CreateContext(). 147501e04c3fSmrg */ 147601e04c3fSmrgstatic _EGLContext * 14777ec681f3Smrgdri2_create_context(_EGLDisplay *disp, _EGLConfig *conf, 147801e04c3fSmrg _EGLContext *share_list, const EGLint *attrib_list) 147901e04c3fSmrg{ 148001e04c3fSmrg struct dri2_egl_context *dri2_ctx; 148101e04c3fSmrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 148201e04c3fSmrg struct dri2_egl_context *dri2_ctx_shared = dri2_egl_context(share_list); 148301e04c3fSmrg __DRIcontext *shared = 148401e04c3fSmrg dri2_ctx_shared ? dri2_ctx_shared->dri_context : NULL; 148501e04c3fSmrg struct dri2_egl_config *dri2_config = dri2_egl_config(conf); 148601e04c3fSmrg const __DRIconfig *dri_config; 148701e04c3fSmrg int api; 148801e04c3fSmrg unsigned error; 148901e04c3fSmrg unsigned num_attribs = NUM_ATTRIBS; 149001e04c3fSmrg uint32_t ctx_attribs[NUM_ATTRIBS]; 149101e04c3fSmrg 149201e04c3fSmrg dri2_ctx = malloc(sizeof *dri2_ctx); 149301e04c3fSmrg if (!dri2_ctx) { 149401e04c3fSmrg _eglError(EGL_BAD_ALLOC, "eglCreateContext"); 149501e04c3fSmrg return NULL; 1496cdc920a0Smrg } 1497cdc920a0Smrg 1498cdc920a0Smrg if (!_eglInitContext(&dri2_ctx->base, disp, conf, attrib_list)) 1499cdc920a0Smrg goto cleanup; 1500cdc920a0Smrg 150101e04c3fSmrg /* The EGL_EXT_create_context_robustness spec says: 150201e04c3fSmrg * 150301e04c3fSmrg * "Add to the eglCreateContext context creation errors: [...] 150401e04c3fSmrg * 150501e04c3fSmrg * * If the reset notification behavior of <share_context> and the 150601e04c3fSmrg * newly created context are different then an EGL_BAD_MATCH error is 150701e04c3fSmrg * generated." 150801e04c3fSmrg */ 150901e04c3fSmrg if (share_list && share_list->ResetNotificationStrategy != 151001e04c3fSmrg dri2_ctx->base.ResetNotificationStrategy) { 151101e04c3fSmrg _eglError(EGL_BAD_MATCH, "eglCreateContext"); 151201e04c3fSmrg goto cleanup; 151301e04c3fSmrg } 151401e04c3fSmrg 151501e04c3fSmrg /* The EGL_KHR_create_context_no_error spec says: 151601e04c3fSmrg * 151701e04c3fSmrg * "BAD_MATCH is generated if the value of EGL_CONTEXT_OPENGL_NO_ERROR_KHR 151801e04c3fSmrg * used to create <share_context> does not match the value of 151901e04c3fSmrg * EGL_CONTEXT_OPENGL_NO_ERROR_KHR for the context being created." 152001e04c3fSmrg */ 152101e04c3fSmrg if (share_list && share_list->NoError != dri2_ctx->base.NoError) { 152201e04c3fSmrg _eglError(EGL_BAD_MATCH, "eglCreateContext"); 152301e04c3fSmrg goto cleanup; 152401e04c3fSmrg } 152501e04c3fSmrg 15263464ebd5Sriastradh switch (dri2_ctx->base.ClientAPI) { 15273464ebd5Sriastradh case EGL_OPENGL_ES_API: 1528af69d88dSmrg switch (dri2_ctx->base.ClientMajorVersion) { 15293464ebd5Sriastradh case 1: 15303464ebd5Sriastradh api = __DRI_API_GLES; 15313464ebd5Sriastradh break; 15323464ebd5Sriastradh case 2: 15333464ebd5Sriastradh api = __DRI_API_GLES2; 15343464ebd5Sriastradh break; 1535af69d88dSmrg case 3: 1536af69d88dSmrg api = __DRI_API_GLES3; 1537af69d88dSmrg break; 15383464ebd5Sriastradh default: 1539af69d88dSmrg _eglError(EGL_BAD_PARAMETER, "eglCreateContext"); 1540af69d88dSmrg free(dri2_ctx); 1541af69d88dSmrg return NULL; 15423464ebd5Sriastradh } 15433464ebd5Sriastradh break; 15443464ebd5Sriastradh case EGL_OPENGL_API: 1545af69d88dSmrg if ((dri2_ctx->base.ClientMajorVersion >= 4 1546af69d88dSmrg || (dri2_ctx->base.ClientMajorVersion == 3 1547af69d88dSmrg && dri2_ctx->base.ClientMinorVersion >= 2)) 1548af69d88dSmrg && dri2_ctx->base.Profile == EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR) 1549af69d88dSmrg api = __DRI_API_OPENGL_CORE; 15507ec681f3Smrg else if (dri2_ctx->base.ClientMajorVersion == 3 && 15517ec681f3Smrg dri2_ctx->base.ClientMinorVersion == 1) 15527ec681f3Smrg api = __DRI_API_OPENGL_CORE; 1553af69d88dSmrg else 1554af69d88dSmrg api = __DRI_API_OPENGL; 15553464ebd5Sriastradh break; 15563464ebd5Sriastradh default: 15573464ebd5Sriastradh _eglError(EGL_BAD_PARAMETER, "eglCreateContext"); 1558af69d88dSmrg free(dri2_ctx); 15593464ebd5Sriastradh return NULL; 15603464ebd5Sriastradh } 15613464ebd5Sriastradh 15623464ebd5Sriastradh if (conf != NULL) { 15633464ebd5Sriastradh /* The config chosen here isn't necessarily 15643464ebd5Sriastradh * used for surfaces later. 15653464ebd5Sriastradh * A pixmap surface will use the single config. 15663464ebd5Sriastradh * This opportunity depends on disabling the 15673464ebd5Sriastradh * doubleBufferMode check in 15683464ebd5Sriastradh * src/mesa/main/context.c:check_compatible() 15693464ebd5Sriastradh */ 157001e04c3fSmrg if (dri2_config->dri_config[1][0]) 157101e04c3fSmrg dri_config = dri2_config->dri_config[1][0]; 15723464ebd5Sriastradh else 157301e04c3fSmrg dri_config = dri2_config->dri_config[0][0]; 15743464ebd5Sriastradh } 15753464ebd5Sriastradh else 15763464ebd5Sriastradh dri_config = NULL; 15773464ebd5Sriastradh 157801e04c3fSmrg if (!dri2_fill_context_attribs(dri2_ctx, dri2_dpy, ctx_attribs, 157901e04c3fSmrg &num_attribs)) 158001e04c3fSmrg goto cleanup; 1581af69d88dSmrg 158201e04c3fSmrg if (dri2_dpy->image_driver) { 158301e04c3fSmrg dri2_ctx->dri_context = 158401e04c3fSmrg dri2_dpy->image_driver->createContextAttribs(dri2_dpy->dri_screen, 158501e04c3fSmrg api, 158601e04c3fSmrg dri_config, 158701e04c3fSmrg shared, 158801e04c3fSmrg num_attribs / 2, 158901e04c3fSmrg ctx_attribs, 159001e04c3fSmrg & error, 159101e04c3fSmrg dri2_ctx); 159201e04c3fSmrg dri2_create_context_attribs_error(error); 159301e04c3fSmrg } else if (dri2_dpy->dri2) { 159401e04c3fSmrg if (dri2_dpy->dri2->base.version >= 3) { 159501e04c3fSmrg dri2_ctx->dri_context = 159601e04c3fSmrg dri2_dpy->dri2->createContextAttribs(dri2_dpy->dri_screen, 1597af69d88dSmrg api, 1598af69d88dSmrg dri_config, 1599af69d88dSmrg shared, 1600af69d88dSmrg num_attribs / 2, 1601af69d88dSmrg ctx_attribs, 1602af69d88dSmrg & error, 1603af69d88dSmrg dri2_ctx); 160401e04c3fSmrg dri2_create_context_attribs_error(error); 1605af69d88dSmrg } else { 160601e04c3fSmrg dri2_ctx->dri_context = 160701e04c3fSmrg dri2_dpy->dri2->createNewContextForAPI(dri2_dpy->dri_screen, 160801e04c3fSmrg api, 160901e04c3fSmrg dri_config, 1610af69d88dSmrg shared, 161101e04c3fSmrg dri2_ctx); 16123464ebd5Sriastradh } 16133464ebd5Sriastradh } else { 16143464ebd5Sriastradh assert(dri2_dpy->swrast); 161501e04c3fSmrg if (dri2_dpy->swrast->base.version >= 3) { 161601e04c3fSmrg dri2_ctx->dri_context = 161701e04c3fSmrg dri2_dpy->swrast->createContextAttribs(dri2_dpy->dri_screen, 161801e04c3fSmrg api, 161901e04c3fSmrg dri_config, 162001e04c3fSmrg shared, 162101e04c3fSmrg num_attribs / 2, 162201e04c3fSmrg ctx_attribs, 162301e04c3fSmrg & error, 162401e04c3fSmrg dri2_ctx); 162501e04c3fSmrg dri2_create_context_attribs_error(error); 162601e04c3fSmrg } else { 162701e04c3fSmrg dri2_ctx->dri_context = 162801e04c3fSmrg dri2_dpy->swrast->createNewContextForAPI(dri2_dpy->dri_screen, 162901e04c3fSmrg api, 163001e04c3fSmrg dri_config, 163101e04c3fSmrg shared, 163201e04c3fSmrg dri2_ctx); 163301e04c3fSmrg } 16343464ebd5Sriastradh } 1635cdc920a0Smrg 1636cdc920a0Smrg if (!dri2_ctx->dri_context) 1637cdc920a0Smrg goto cleanup; 1638cdc920a0Smrg 1639cdc920a0Smrg return &dri2_ctx->base; 1640cdc920a0Smrg 1641cdc920a0Smrg cleanup: 1642cdc920a0Smrg free(dri2_ctx); 1643cdc920a0Smrg return NULL; 1644cdc920a0Smrg} 1645cdc920a0Smrg 1646af69d88dSmrg/** 16477ec681f3Smrg * Called via eglDestroyContext(), drv->DestroyContext(). 1648af69d88dSmrg */ 1649af69d88dSmrgstatic EGLBoolean 16507ec681f3Smrgdri2_destroy_context(_EGLDisplay *disp, _EGLContext *ctx) 1651af69d88dSmrg{ 1652af69d88dSmrg struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); 1653af69d88dSmrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1654af69d88dSmrg 1655af69d88dSmrg if (_eglPutContext(ctx)) { 1656af69d88dSmrg dri2_dpy->core->destroyContext(dri2_ctx->dri_context); 1657af69d88dSmrg free(dri2_ctx); 1658af69d88dSmrg } 1659af69d88dSmrg 1660af69d88dSmrg return EGL_TRUE; 1661af69d88dSmrg} 1662af69d88dSmrg 166301e04c3fSmrgEGLBoolean 16647e102996Smayadri2_init_surface(_EGLSurface *surf, _EGLDisplay *disp, EGLint type, 16657ec681f3Smrg _EGLConfig *conf, const EGLint *attrib_list, 16667ec681f3Smrg EGLBoolean enable_out_fence, void *native_surface) 166701e04c3fSmrg{ 166801e04c3fSmrg struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); 16697e102996Smaya struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 167001e04c3fSmrg 167101e04c3fSmrg dri2_surf->out_fence_fd = -1; 167201e04c3fSmrg dri2_surf->enable_out_fence = false; 167301e04c3fSmrg if (dri2_dpy->fence && dri2_dpy->fence->base.version >= 2 && 167401e04c3fSmrg dri2_dpy->fence->get_capabilities && 167501e04c3fSmrg (dri2_dpy->fence->get_capabilities(dri2_dpy->dri_screen) & 167601e04c3fSmrg __DRI_FENCE_CAP_NATIVE_FD)) { 167701e04c3fSmrg dri2_surf->enable_out_fence = enable_out_fence; 167801e04c3fSmrg } 167901e04c3fSmrg 16807ec681f3Smrg return _eglInitSurface(surf, disp, type, conf, attrib_list, native_surface); 168101e04c3fSmrg} 168201e04c3fSmrg 168301e04c3fSmrgstatic void 168401e04c3fSmrgdri2_surface_set_out_fence_fd( _EGLSurface *surf, int fence_fd) 168501e04c3fSmrg{ 168601e04c3fSmrg struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); 168701e04c3fSmrg 168801e04c3fSmrg if (dri2_surf->out_fence_fd >= 0) 168901e04c3fSmrg close(dri2_surf->out_fence_fd); 169001e04c3fSmrg 169101e04c3fSmrg dri2_surf->out_fence_fd = fence_fd; 169201e04c3fSmrg} 169301e04c3fSmrg 169401e04c3fSmrgvoid 169501e04c3fSmrgdri2_fini_surface(_EGLSurface *surf) 169601e04c3fSmrg{ 169701e04c3fSmrg struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); 169801e04c3fSmrg 169901e04c3fSmrg dri2_surface_set_out_fence_fd(surf, -1); 170001e04c3fSmrg dri2_surf->enable_out_fence = false; 170101e04c3fSmrg} 170201e04c3fSmrg 170301e04c3fSmrgstatic EGLBoolean 17047ec681f3Smrgdri2_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf) 170501e04c3fSmrg{ 17067e102996Smaya struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 170701e04c3fSmrg 170801e04c3fSmrg if (!_eglPutSurface(surf)) 170901e04c3fSmrg return EGL_TRUE; 171001e04c3fSmrg 17117ec681f3Smrg return dri2_dpy->vtbl->destroy_surface(disp, surf); 171201e04c3fSmrg} 171301e04c3fSmrg 171401e04c3fSmrgstatic void 171501e04c3fSmrgdri2_surf_update_fence_fd(_EGLContext *ctx, 17167e102996Smaya _EGLDisplay *disp, _EGLSurface *surf) 171701e04c3fSmrg{ 171801e04c3fSmrg __DRIcontext *dri_ctx = dri2_egl_context(ctx)->dri_context; 17197e102996Smaya struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 172001e04c3fSmrg struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); 172101e04c3fSmrg int fence_fd = -1; 172201e04c3fSmrg void *fence; 172301e04c3fSmrg 172401e04c3fSmrg if (!dri2_surf->enable_out_fence) 172501e04c3fSmrg return; 172601e04c3fSmrg 172701e04c3fSmrg fence = dri2_dpy->fence->create_fence_fd(dri_ctx, -1); 172801e04c3fSmrg if (fence) { 172901e04c3fSmrg fence_fd = dri2_dpy->fence->get_fence_fd(dri2_dpy->dri_screen, 173001e04c3fSmrg fence); 173101e04c3fSmrg dri2_dpy->fence->destroy_fence(dri2_dpy->dri_screen, fence); 173201e04c3fSmrg } 173301e04c3fSmrg dri2_surface_set_out_fence_fd(surf, fence_fd); 173401e04c3fSmrg} 173501e04c3fSmrg 17367e102996SmayaEGLBoolean 17377e102996Smayadri2_create_drawable(struct dri2_egl_display *dri2_dpy, 17387e102996Smaya const __DRIconfig *config, 17397ec681f3Smrg struct dri2_egl_surface *dri2_surf, 17407ec681f3Smrg void *loaderPrivate) 17417e102996Smaya{ 17427e102996Smaya __DRIcreateNewDrawableFunc createNewDrawable; 17437e102996Smaya 17447e102996Smaya if (dri2_dpy->image_driver) 17457e102996Smaya createNewDrawable = dri2_dpy->image_driver->createNewDrawable; 17467e102996Smaya else if (dri2_dpy->dri2) 17477e102996Smaya createNewDrawable = dri2_dpy->dri2->createNewDrawable; 17487e102996Smaya else if (dri2_dpy->swrast) 17497e102996Smaya createNewDrawable = dri2_dpy->swrast->createNewDrawable; 17507e102996Smaya else 17517e102996Smaya return _eglError(EGL_BAD_ALLOC, "no createNewDrawable"); 17527e102996Smaya 17537ec681f3Smrg dri2_surf->dri_drawable = createNewDrawable(dri2_dpy->dri_screen, 17547ec681f3Smrg config, loaderPrivate); 17557e102996Smaya if (dri2_surf->dri_drawable == NULL) 17567e102996Smaya return _eglError(EGL_BAD_ALLOC, "createNewDrawable"); 17577e102996Smaya 17587e102996Smaya return EGL_TRUE; 17597e102996Smaya} 17607e102996Smaya 1761cdc920a0Smrg/** 17627ec681f3Smrg * Called via eglMakeCurrent(), drv->MakeCurrent(). 1763cdc920a0Smrg */ 1764cdc920a0Smrgstatic EGLBoolean 17657ec681f3Smrgdri2_make_current(_EGLDisplay *disp, _EGLSurface *dsurf, 176601e04c3fSmrg _EGLSurface *rsurf, _EGLContext *ctx) 1767cdc920a0Smrg{ 1768cdc920a0Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1769cdc920a0Smrg struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); 177001e04c3fSmrg _EGLDisplay *old_disp = NULL; 177101e04c3fSmrg struct dri2_egl_display *old_dri2_dpy = NULL; 17723464ebd5Sriastradh _EGLContext *old_ctx; 17733464ebd5Sriastradh _EGLSurface *old_dsurf, *old_rsurf; 177401e04c3fSmrg _EGLSurface *tmp_dsurf, *tmp_rsurf; 1775cdc920a0Smrg __DRIdrawable *ddraw, *rdraw; 1776cdc920a0Smrg __DRIcontext *cctx; 17777ec681f3Smrg EGLint egl_error = EGL_SUCCESS; 177801e04c3fSmrg 177901e04c3fSmrg if (!dri2_dpy) 178001e04c3fSmrg return _eglError(EGL_NOT_INITIALIZED, "eglMakeCurrent"); 1781cdc920a0Smrg 17827ec681f3Smrg /* make new bindings, set the EGL error otherwise */ 17837ec681f3Smrg if (!_eglBindContext(ctx, dsurf, rsurf, &old_ctx, &old_dsurf, &old_rsurf)) 1784cdc920a0Smrg return EGL_FALSE; 178501e04c3fSmrg 178601e04c3fSmrg if (old_ctx) { 17877ec681f3Smrg __DRIcontext *old_cctx = dri2_egl_context(old_ctx)->dri_context; 178801e04c3fSmrg old_disp = old_ctx->Resource.Display; 178901e04c3fSmrg old_dri2_dpy = dri2_egl_display(old_disp); 1790cdc920a0Smrg 17917ec681f3Smrg /* flush before context switch */ 179201e04c3fSmrg dri2_gl_flush(); 17933464ebd5Sriastradh 179401e04c3fSmrg if (old_dsurf) 179501e04c3fSmrg dri2_surf_update_fence_fd(old_ctx, disp, old_dsurf); 179601e04c3fSmrg 179701e04c3fSmrg /* Disable shared buffer mode */ 179801e04c3fSmrg if (old_dsurf && _eglSurfaceInSharedBufferMode(old_dsurf) && 179901e04c3fSmrg old_dri2_dpy->vtbl->set_shared_buffer_mode) { 180001e04c3fSmrg old_dri2_dpy->vtbl->set_shared_buffer_mode(old_disp, old_dsurf, false); 180101e04c3fSmrg } 180201e04c3fSmrg 18033464ebd5Sriastradh dri2_dpy->core->unbindContext(old_cctx); 18043464ebd5Sriastradh } 18053464ebd5Sriastradh 18067ec681f3Smrg ddraw = (dsurf) ? dri2_dpy->vtbl->get_dri_drawable(dsurf) : NULL; 18077ec681f3Smrg rdraw = (rsurf) ? dri2_dpy->vtbl->get_dri_drawable(rsurf) : NULL; 18087ec681f3Smrg cctx = (dri2_ctx) ? dri2_ctx->dri_context : NULL; 1809cdc920a0Smrg 18107ec681f3Smrg if (cctx || ddraw || rdraw) { 18117ec681f3Smrg if (!dri2_dpy->core->bindContext(cctx, ddraw, rdraw)) { 18127ec681f3Smrg _EGLContext *tmp_ctx; 181301e04c3fSmrg 18147ec681f3Smrg /* dri2_dpy->core->bindContext failed. We cannot tell for sure why, but 18157ec681f3Smrg * setting the error to EGL_BAD_MATCH is surely better than leaving it 18167ec681f3Smrg * as EGL_SUCCESS. 18177ec681f3Smrg */ 18187ec681f3Smrg egl_error = EGL_BAD_MATCH; 18197ec681f3Smrg 18207ec681f3Smrg /* undo the previous _eglBindContext */ 18217ec681f3Smrg _eglBindContext(old_ctx, old_dsurf, old_rsurf, &ctx, &tmp_dsurf, &tmp_rsurf); 18227ec681f3Smrg assert(&dri2_ctx->base == ctx && 18237ec681f3Smrg tmp_dsurf == dsurf && 18247ec681f3Smrg tmp_rsurf == rsurf); 18257ec681f3Smrg 18267ec681f3Smrg _eglPutSurface(dsurf); 18277ec681f3Smrg _eglPutSurface(rsurf); 18287ec681f3Smrg _eglPutContext(ctx); 18297ec681f3Smrg 18307ec681f3Smrg _eglPutSurface(old_dsurf); 18317ec681f3Smrg _eglPutSurface(old_rsurf); 18327ec681f3Smrg _eglPutContext(old_ctx); 18337ec681f3Smrg 18347ec681f3Smrg ddraw = (old_dsurf) ? dri2_dpy->vtbl->get_dri_drawable(old_dsurf) : NULL; 18357ec681f3Smrg rdraw = (old_rsurf) ? dri2_dpy->vtbl->get_dri_drawable(old_rsurf) : NULL; 18367ec681f3Smrg cctx = (old_ctx) ? dri2_egl_context(old_ctx)->dri_context : NULL; 18377ec681f3Smrg 18387ec681f3Smrg /* undo the previous dri2_dpy->core->unbindContext */ 18397ec681f3Smrg if (dri2_dpy->core->bindContext(cctx, ddraw, rdraw)) { 18407ec681f3Smrg if (old_dsurf && _eglSurfaceInSharedBufferMode(old_dsurf) && 18417ec681f3Smrg old_dri2_dpy->vtbl->set_shared_buffer_mode) { 18427ec681f3Smrg old_dri2_dpy->vtbl->set_shared_buffer_mode(old_disp, old_dsurf, true); 18437ec681f3Smrg } 18443464ebd5Sriastradh 18457ec681f3Smrg return _eglError(egl_error, "eglMakeCurrent"); 18467ec681f3Smrg } 18473464ebd5Sriastradh 18487ec681f3Smrg /* We cannot restore the same state as it was before calling 18497ec681f3Smrg * eglMakeCurrent() and the spec isn't clear about what to do. We 18507ec681f3Smrg * can prevent EGL from calling into the DRI driver with no DRI 18517ec681f3Smrg * context bound. 18527ec681f3Smrg */ 18537ec681f3Smrg dsurf = rsurf = NULL; 18547ec681f3Smrg ctx = NULL; 1855cdc920a0Smrg 18567ec681f3Smrg _eglBindContext(ctx, dsurf, rsurf, &tmp_ctx, &tmp_dsurf, &tmp_rsurf); 18577ec681f3Smrg assert(tmp_ctx == old_ctx && tmp_dsurf == old_dsurf && 18587ec681f3Smrg tmp_rsurf == old_rsurf); 185901e04c3fSmrg 18607ec681f3Smrg _eglLog(_EGL_WARNING, "DRI2: failed to rebind the previous context"); 18617ec681f3Smrg } else { 18627ec681f3Smrg /* dri2_dpy->core->bindContext succeeded, so take a reference on the 18637ec681f3Smrg * dri2_dpy. This prevents dri2_dpy from being reinitialized when a 18647ec681f3Smrg * EGLDisplay is terminated and then initialized again while a 18657ec681f3Smrg * context is still bound. See dri2_intitialize() for a more in depth 18667ec681f3Smrg * explanation. */ 18677ec681f3Smrg dri2_dpy->ref_count++; 18687ec681f3Smrg } 18697ec681f3Smrg } 187001e04c3fSmrg 18717ec681f3Smrg dri2_destroy_surface(disp, old_dsurf); 18727ec681f3Smrg dri2_destroy_surface(disp, old_rsurf); 187301e04c3fSmrg 187401e04c3fSmrg if (old_ctx) { 18757ec681f3Smrg dri2_destroy_context(disp, old_ctx); 187601e04c3fSmrg dri2_display_release(old_disp); 1877cdc920a0Smrg } 187801e04c3fSmrg 18797ec681f3Smrg if (egl_error != EGL_SUCCESS) 18807ec681f3Smrg return _eglError(egl_error, "eglMakeCurrent"); 18817ec681f3Smrg 188201e04c3fSmrg if (dsurf && _eglSurfaceHasMutableRenderBuffer(dsurf) && 188301e04c3fSmrg dri2_dpy->vtbl->set_shared_buffer_mode) { 188401e04c3fSmrg /* Always update the shared buffer mode. This is obviously needed when 188501e04c3fSmrg * the active EGL_RENDER_BUFFER is EGL_SINGLE_BUFFER. When 188601e04c3fSmrg * EGL_RENDER_BUFFER is EGL_BACK_BUFFER, the update protects us in the 188701e04c3fSmrg * case where external non-EGL API may have changed window's shared 188801e04c3fSmrg * buffer mode since we last saw it. 188901e04c3fSmrg */ 189001e04c3fSmrg bool mode = (dsurf->ActiveRenderBuffer == EGL_SINGLE_BUFFER); 189101e04c3fSmrg dri2_dpy->vtbl->set_shared_buffer_mode(disp, dsurf, mode); 189201e04c3fSmrg } 189301e04c3fSmrg 189401e04c3fSmrg return EGL_TRUE; 189501e04c3fSmrg} 189601e04c3fSmrg 189701e04c3fSmrg__DRIdrawable * 189801e04c3fSmrgdri2_surface_get_dri_drawable(_EGLSurface *surf) 189901e04c3fSmrg{ 190001e04c3fSmrg struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); 190101e04c3fSmrg 190201e04c3fSmrg return dri2_surf->dri_drawable; 1903cdc920a0Smrg} 1904cdc920a0Smrg 19053464ebd5Sriastradh/* 19067ec681f3Smrg * Called from eglGetProcAddress() via drv->GetProcAddress(). 1907cdc920a0Smrg */ 19083464ebd5Sriastradhstatic _EGLProc 19097ec681f3Smrgdri2_get_proc_address(const char *procname) 1910cdc920a0Smrg{ 191101e04c3fSmrg return _glapi_get_proc_address(procname); 1912cdc920a0Smrg} 1913cdc920a0Smrg 1914af69d88dSmrgstatic _EGLSurface* 19157ec681f3Smrgdri2_create_window_surface(_EGLDisplay *disp, _EGLConfig *conf, 19167ec681f3Smrg void *native_window, const EGLint *attrib_list) 1917af69d88dSmrg{ 19187e102996Smaya struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 19197ec681f3Smrg return dri2_dpy->vtbl->create_window_surface(disp, conf, native_window, 1920af69d88dSmrg attrib_list); 1921af69d88dSmrg} 1922af69d88dSmrg 1923af69d88dSmrgstatic _EGLSurface* 19247ec681f3Smrgdri2_create_pixmap_surface(_EGLDisplay *disp, _EGLConfig *conf, 19257ec681f3Smrg void *native_pixmap, const EGLint *attrib_list) 1926af69d88dSmrg{ 19277e102996Smaya struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 19287ec681f3Smrg if (!dri2_dpy->vtbl->create_pixmap_surface) 19297ec681f3Smrg return NULL; 19307ec681f3Smrg return dri2_dpy->vtbl->create_pixmap_surface(disp, conf, native_pixmap, 1931af69d88dSmrg attrib_list); 1932af69d88dSmrg} 1933af69d88dSmrg 1934af69d88dSmrgstatic _EGLSurface* 19357ec681f3Smrgdri2_create_pbuffer_surface(_EGLDisplay *disp, _EGLConfig *conf, 19367ec681f3Smrg const EGLint *attrib_list) 1937af69d88dSmrg{ 19387e102996Smaya struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 19397ec681f3Smrg if (!dri2_dpy->vtbl->create_pbuffer_surface) 19407ec681f3Smrg return NULL; 19417ec681f3Smrg return dri2_dpy->vtbl->create_pbuffer_surface(disp, conf, attrib_list); 1942af69d88dSmrg} 1943af69d88dSmrg 1944af69d88dSmrgstatic EGLBoolean 19457ec681f3Smrgdri2_swap_interval(_EGLDisplay *disp, _EGLSurface *surf, EGLint interval) 1946af69d88dSmrg{ 19477e102996Smaya struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 194801e04c3fSmrg if (!dri2_dpy->vtbl->swap_interval) 194901e04c3fSmrg return EGL_TRUE; 19507ec681f3Smrg return dri2_dpy->vtbl->swap_interval(disp, surf, interval); 1951af69d88dSmrg} 1952af69d88dSmrg 195301e04c3fSmrg/** 195401e04c3fSmrg * Asks the client API to flush any rendering to the drawable so that we can 195501e04c3fSmrg * do our swapbuffers. 195601e04c3fSmrg */ 195701e04c3fSmrgvoid 195801e04c3fSmrgdri2_flush_drawable_for_swapbuffers(_EGLDisplay *disp, _EGLSurface *draw) 195901e04c3fSmrg{ 196001e04c3fSmrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 196101e04c3fSmrg __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(draw); 196201e04c3fSmrg 196301e04c3fSmrg if (dri2_dpy->flush) { 196401e04c3fSmrg if (dri2_dpy->flush->base.version >= 4) { 196501e04c3fSmrg /* We know there's a current context because: 196601e04c3fSmrg * 196701e04c3fSmrg * "If surface is not bound to the calling thread’s current 196801e04c3fSmrg * context, an EGL_BAD_SURFACE error is generated." 196901e04c3fSmrg */ 197001e04c3fSmrg _EGLContext *ctx = _eglGetCurrentContext(); 197101e04c3fSmrg struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); 197201e04c3fSmrg 197301e04c3fSmrg /* From the EGL 1.4 spec (page 52): 197401e04c3fSmrg * 197501e04c3fSmrg * "The contents of ancillary buffers are always undefined 197601e04c3fSmrg * after calling eglSwapBuffers." 197701e04c3fSmrg */ 197801e04c3fSmrg dri2_dpy->flush->flush_with_flags(dri2_ctx->dri_context, 197901e04c3fSmrg dri_drawable, 198001e04c3fSmrg __DRI2_FLUSH_DRAWABLE | 198101e04c3fSmrg __DRI2_FLUSH_INVALIDATE_ANCILLARY, 198201e04c3fSmrg __DRI2_THROTTLE_SWAPBUFFER); 198301e04c3fSmrg } else { 198401e04c3fSmrg dri2_dpy->flush->flush(dri_drawable); 198501e04c3fSmrg } 198601e04c3fSmrg } 198701e04c3fSmrg} 198801e04c3fSmrg 1989af69d88dSmrgstatic EGLBoolean 19907ec681f3Smrgdri2_swap_buffers(_EGLDisplay *disp, _EGLSurface *surf) 1991af69d88dSmrg{ 19927e102996Smaya struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 19937ec681f3Smrg __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(surf); 199401e04c3fSmrg _EGLContext *ctx = _eglGetCurrentContext(); 19957ec681f3Smrg EGLBoolean ret; 199601e04c3fSmrg 199701e04c3fSmrg if (ctx && surf) 19987e102996Smaya dri2_surf_update_fence_fd(ctx, disp, surf); 19997ec681f3Smrg ret = dri2_dpy->vtbl->swap_buffers(disp, surf); 20007ec681f3Smrg 20017ec681f3Smrg /* SwapBuffers marks the end of the frame; reset the damage region for 20027ec681f3Smrg * use again next time. 20037ec681f3Smrg */ 20047ec681f3Smrg if (ret && dri2_dpy->buffer_damage && 20057ec681f3Smrg dri2_dpy->buffer_damage->set_damage_region) 20067ec681f3Smrg dri2_dpy->buffer_damage->set_damage_region(dri_drawable, 0, NULL); 20077ec681f3Smrg 20087ec681f3Smrg return ret; 2009af69d88dSmrg} 2010af69d88dSmrg 2011af69d88dSmrgstatic EGLBoolean 20127ec681f3Smrgdri2_swap_buffers_with_damage(_EGLDisplay *disp, _EGLSurface *surf, 2013af69d88dSmrg const EGLint *rects, EGLint n_rects) 2014af69d88dSmrg{ 20157e102996Smaya struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 20167ec681f3Smrg __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(surf); 201701e04c3fSmrg _EGLContext *ctx = _eglGetCurrentContext(); 20187ec681f3Smrg EGLBoolean ret; 201901e04c3fSmrg 202001e04c3fSmrg if (ctx && surf) 20217e102996Smaya dri2_surf_update_fence_fd(ctx, disp, surf); 20227ec681f3Smrg if (dri2_dpy->vtbl->swap_buffers_with_damage) 20237ec681f3Smrg ret = dri2_dpy->vtbl->swap_buffers_with_damage(disp, surf, 20247ec681f3Smrg rects, n_rects); 20257ec681f3Smrg else 20267ec681f3Smrg ret = dri2_dpy->vtbl->swap_buffers(disp, surf); 20277ec681f3Smrg 20287ec681f3Smrg /* SwapBuffers marks the end of the frame; reset the damage region for 20297ec681f3Smrg * use again next time. 20307ec681f3Smrg */ 20317ec681f3Smrg if (ret && dri2_dpy->buffer_damage && 20327ec681f3Smrg dri2_dpy->buffer_damage->set_damage_region) 20337ec681f3Smrg dri2_dpy->buffer_damage->set_damage_region(dri_drawable, 0, NULL); 20347ec681f3Smrg 20357ec681f3Smrg return ret; 2036af69d88dSmrg} 2037af69d88dSmrg 2038af69d88dSmrgstatic EGLBoolean 20397ec681f3Smrgdri2_swap_buffers_region(_EGLDisplay *disp, _EGLSurface *surf, 2040af69d88dSmrg EGLint numRects, const EGLint *rects) 2041af69d88dSmrg{ 20427e102996Smaya struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 20437ec681f3Smrg __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(surf); 20447ec681f3Smrg EGLBoolean ret; 20457ec681f3Smrg 20467ec681f3Smrg if (!dri2_dpy->vtbl->swap_buffers_region) 20477ec681f3Smrg return EGL_FALSE; 20487ec681f3Smrg ret = dri2_dpy->vtbl->swap_buffers_region(disp, surf, numRects, rects); 20497ec681f3Smrg 20507ec681f3Smrg /* SwapBuffers marks the end of the frame; reset the damage region for 20517ec681f3Smrg * use again next time. 20527ec681f3Smrg */ 20537ec681f3Smrg if (ret && dri2_dpy->buffer_damage && 20547ec681f3Smrg dri2_dpy->buffer_damage->set_damage_region) 20557ec681f3Smrg dri2_dpy->buffer_damage->set_damage_region(dri_drawable, 0, NULL); 20567ec681f3Smrg 20577ec681f3Smrg return ret; 2058af69d88dSmrg} 2059af69d88dSmrg 206001e04c3fSmrgstatic EGLBoolean 20617ec681f3Smrgdri2_set_damage_region(_EGLDisplay *disp, _EGLSurface *surf, 206201e04c3fSmrg EGLint *rects, EGLint n_rects) 206301e04c3fSmrg{ 20647e102996Smaya struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 20657ec681f3Smrg __DRIdrawable *drawable = dri2_dpy->vtbl->get_dri_drawable(surf); 20667ec681f3Smrg 20677ec681f3Smrg if (!dri2_dpy->buffer_damage || !dri2_dpy->buffer_damage->set_damage_region) 20687ec681f3Smrg return EGL_FALSE; 20697ec681f3Smrg 20707ec681f3Smrg dri2_dpy->buffer_damage->set_damage_region(drawable, n_rects, rects); 20717ec681f3Smrg return EGL_TRUE; 207201e04c3fSmrg} 207301e04c3fSmrg 2074af69d88dSmrgstatic EGLBoolean 20757ec681f3Smrgdri2_post_sub_buffer(_EGLDisplay *disp, _EGLSurface *surf, 2076af69d88dSmrg EGLint x, EGLint y, EGLint width, EGLint height) 2077af69d88dSmrg{ 20787e102996Smaya struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 20797ec681f3Smrg if (!dri2_dpy->vtbl->post_sub_buffer) 20807ec681f3Smrg return EGL_FALSE; 20817ec681f3Smrg return dri2_dpy->vtbl->post_sub_buffer(disp, surf, x, y, width, height); 2082af69d88dSmrg} 2083af69d88dSmrg 2084af69d88dSmrgstatic EGLBoolean 20857ec681f3Smrgdri2_copy_buffers(_EGLDisplay *disp, _EGLSurface *surf, void *native_pixmap_target) 2086af69d88dSmrg{ 20877e102996Smaya struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 20887ec681f3Smrg if (!dri2_dpy->vtbl->copy_buffers) 20897ec681f3Smrg return _eglError(EGL_BAD_NATIVE_PIXMAP, "no support for native pixmaps"); 20907ec681f3Smrg return dri2_dpy->vtbl->copy_buffers(disp, surf, native_pixmap_target); 2091af69d88dSmrg} 2092af69d88dSmrg 2093af69d88dSmrgstatic EGLint 20947ec681f3Smrgdri2_query_buffer_age(_EGLDisplay *disp, _EGLSurface *surf) 2095af69d88dSmrg{ 20967e102996Smaya struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 20977ec681f3Smrg if (!dri2_dpy->vtbl->query_buffer_age) 20987ec681f3Smrg return 0; 20997ec681f3Smrg return dri2_dpy->vtbl->query_buffer_age(disp, surf); 2100af69d88dSmrg} 2101af69d88dSmrg 2102cdc920a0Smrgstatic EGLBoolean 21037ec681f3Smrgdri2_wait_client(_EGLDisplay *disp, _EGLContext *ctx) 2104cdc920a0Smrg{ 2105cdc920a0Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 210601e04c3fSmrg _EGLSurface *surf = ctx->DrawSurface; 210701e04c3fSmrg __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(surf); 2108cdc920a0Smrg 2109cdc920a0Smrg /* FIXME: If EGL allows frontbuffer rendering for window surfaces, 2110cdc920a0Smrg * we need to copy fake to real here.*/ 2111cdc920a0Smrg 2112af69d88dSmrg if (dri2_dpy->flush != NULL) 211301e04c3fSmrg dri2_dpy->flush->flush(dri_drawable); 2114cdc920a0Smrg 2115cdc920a0Smrg return EGL_TRUE; 2116cdc920a0Smrg} 2117cdc920a0Smrg 2118cdc920a0Smrgstatic EGLBoolean 21197ec681f3Smrgdri2_wait_native(EGLint engine) 2120cdc920a0Smrg{ 2121cdc920a0Smrg if (engine != EGL_CORE_NATIVE_ENGINE) 2122cdc920a0Smrg return _eglError(EGL_BAD_PARAMETER, "eglWaitNative"); 2123cdc920a0Smrg /* glXWaitX(); */ 2124cdc920a0Smrg 2125cdc920a0Smrg return EGL_TRUE; 2126cdc920a0Smrg} 2127cdc920a0Smrg 2128cdc920a0Smrgstatic EGLBoolean 21297ec681f3Smrgdri2_bind_tex_image(_EGLDisplay *disp, _EGLSurface *surf, EGLint buffer) 2130cdc920a0Smrg{ 2131cdc920a0Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2132cdc920a0Smrg struct dri2_egl_context *dri2_ctx; 2133cdc920a0Smrg _EGLContext *ctx; 2134cdc920a0Smrg GLint format, target; 213501e04c3fSmrg __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(surf); 2136cdc920a0Smrg 2137cdc920a0Smrg ctx = _eglGetCurrentContext(); 2138cdc920a0Smrg dri2_ctx = dri2_egl_context(ctx); 2139cdc920a0Smrg 21407ec681f3Smrg if (!_eglBindTexImage(disp, surf, buffer)) 2141cdc920a0Smrg return EGL_FALSE; 2142cdc920a0Smrg 214301e04c3fSmrg switch (surf->TextureFormat) { 2144cdc920a0Smrg case EGL_TEXTURE_RGB: 2145cdc920a0Smrg format = __DRI_TEXTURE_FORMAT_RGB; 2146cdc920a0Smrg break; 2147cdc920a0Smrg case EGL_TEXTURE_RGBA: 2148cdc920a0Smrg format = __DRI_TEXTURE_FORMAT_RGBA; 2149cdc920a0Smrg break; 2150cdc920a0Smrg default: 215101e04c3fSmrg assert(!"Unexpected texture format in dri2_bind_tex_image()"); 215201e04c3fSmrg format = __DRI_TEXTURE_FORMAT_RGBA; 2153cdc920a0Smrg } 2154cdc920a0Smrg 215501e04c3fSmrg switch (surf->TextureTarget) { 2156cdc920a0Smrg case EGL_TEXTURE_2D: 2157cdc920a0Smrg target = GL_TEXTURE_2D; 2158cdc920a0Smrg break; 2159cdc920a0Smrg default: 216001e04c3fSmrg target = GL_TEXTURE_2D; 216101e04c3fSmrg assert(!"Unexpected texture target in dri2_bind_tex_image()"); 2162cdc920a0Smrg } 2163cdc920a0Smrg 216401e04c3fSmrg dri2_dpy->tex_buffer->setTexBuffer2(dri2_ctx->dri_context, 216501e04c3fSmrg target, format, 216601e04c3fSmrg dri_drawable); 2167cdc920a0Smrg 21683464ebd5Sriastradh return EGL_TRUE; 2169cdc920a0Smrg} 2170cdc920a0Smrg 2171cdc920a0Smrgstatic EGLBoolean 21727ec681f3Smrgdri2_release_tex_image(_EGLDisplay *disp, _EGLSurface *surf, EGLint buffer) 2173cdc920a0Smrg{ 21743464ebd5Sriastradh struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 21753464ebd5Sriastradh struct dri2_egl_context *dri2_ctx; 21763464ebd5Sriastradh _EGLContext *ctx; 21773464ebd5Sriastradh GLint target; 217801e04c3fSmrg __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(surf); 21793464ebd5Sriastradh 21803464ebd5Sriastradh ctx = _eglGetCurrentContext(); 21813464ebd5Sriastradh dri2_ctx = dri2_egl_context(ctx); 21823464ebd5Sriastradh 21837ec681f3Smrg if (!_eglReleaseTexImage(disp, surf, buffer)) 21843464ebd5Sriastradh return EGL_FALSE; 21853464ebd5Sriastradh 218601e04c3fSmrg switch (surf->TextureTarget) { 21873464ebd5Sriastradh case EGL_TEXTURE_2D: 21883464ebd5Sriastradh target = GL_TEXTURE_2D; 21893464ebd5Sriastradh break; 21903464ebd5Sriastradh default: 219101e04c3fSmrg assert(!"missing texture target"); 21923464ebd5Sriastradh } 2193af69d88dSmrg 2194af69d88dSmrg if (dri2_dpy->tex_buffer->base.version >= 3 && 2195af69d88dSmrg dri2_dpy->tex_buffer->releaseTexBuffer != NULL) { 219601e04c3fSmrg dri2_dpy->tex_buffer->releaseTexBuffer(dri2_ctx->dri_context, 219701e04c3fSmrg target, dri_drawable); 2198af69d88dSmrg } 21993464ebd5Sriastradh 2200cdc920a0Smrg return EGL_TRUE; 2201cdc920a0Smrg} 2202cdc920a0Smrg 2203af69d88dSmrgstatic _EGLImage* 22047ec681f3Smrgdri2_create_image(_EGLDisplay *disp, _EGLContext *ctx, EGLenum target, 22057ec681f3Smrg EGLClientBuffer buffer, const EGLint *attr_list) 2206af69d88dSmrg{ 22077e102996Smaya struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 22087ec681f3Smrg return dri2_dpy->vtbl->create_image(disp, ctx, target, buffer, 2209af69d88dSmrg attr_list); 2210af69d88dSmrg} 2211af69d88dSmrg 22127ec681f3Smrg_EGLImage * 2213af69d88dSmrgdri2_create_image_from_dri(_EGLDisplay *disp, __DRIimage *dri_image) 2214af69d88dSmrg{ 2215af69d88dSmrg struct dri2_egl_image *dri2_img; 2216af69d88dSmrg 2217af69d88dSmrg if (dri_image == NULL) { 2218af69d88dSmrg _eglError(EGL_BAD_ALLOC, "dri2_create_image"); 2219af69d88dSmrg return NULL; 2220af69d88dSmrg } 2221af69d88dSmrg 2222af69d88dSmrg dri2_img = malloc(sizeof *dri2_img); 2223af69d88dSmrg if (!dri2_img) { 2224af69d88dSmrg _eglError(EGL_BAD_ALLOC, "dri2_create_image"); 2225af69d88dSmrg return NULL; 2226af69d88dSmrg } 2227af69d88dSmrg 222801e04c3fSmrg _eglInitImage(&dri2_img->base, disp); 2229af69d88dSmrg 2230af69d88dSmrg dri2_img->dri_image = dri_image; 2231af69d88dSmrg 2232af69d88dSmrg return &dri2_img->base; 2233af69d88dSmrg} 2234af69d88dSmrg 223501e04c3fSmrg/** 223601e04c3fSmrg * Translate a DRI Image extension error code into an EGL error code. 223701e04c3fSmrg */ 223801e04c3fSmrgstatic EGLint 223901e04c3fSmrgegl_error_from_dri_image_error(int dri_error) 224001e04c3fSmrg{ 224101e04c3fSmrg switch (dri_error) { 224201e04c3fSmrg case __DRI_IMAGE_ERROR_SUCCESS: 224301e04c3fSmrg return EGL_SUCCESS; 224401e04c3fSmrg case __DRI_IMAGE_ERROR_BAD_ALLOC: 224501e04c3fSmrg return EGL_BAD_ALLOC; 224601e04c3fSmrg case __DRI_IMAGE_ERROR_BAD_MATCH: 224701e04c3fSmrg return EGL_BAD_MATCH; 224801e04c3fSmrg case __DRI_IMAGE_ERROR_BAD_PARAMETER: 224901e04c3fSmrg return EGL_BAD_PARAMETER; 225001e04c3fSmrg case __DRI_IMAGE_ERROR_BAD_ACCESS: 225101e04c3fSmrg return EGL_BAD_ACCESS; 225201e04c3fSmrg default: 225301e04c3fSmrg assert(!"unknown dri_error code"); 225401e04c3fSmrg return EGL_BAD_ALLOC; 225501e04c3fSmrg } 225601e04c3fSmrg} 225701e04c3fSmrg 2258cdc920a0Smrgstatic _EGLImage * 22593464ebd5Sriastradhdri2_create_image_khr_renderbuffer(_EGLDisplay *disp, _EGLContext *ctx, 226001e04c3fSmrg EGLClientBuffer buffer, 226101e04c3fSmrg const EGLint *attr_list) 2262cdc920a0Smrg{ 2263cdc920a0Smrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2264cdc920a0Smrg struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); 22653464ebd5Sriastradh GLuint renderbuffer = (GLuint) (uintptr_t) buffer; 2266af69d88dSmrg __DRIimage *dri_image; 22673464ebd5Sriastradh 22683464ebd5Sriastradh if (renderbuffer == 0) { 22693464ebd5Sriastradh _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr"); 22703464ebd5Sriastradh return EGL_NO_IMAGE_KHR; 2271cdc920a0Smrg } 2272cdc920a0Smrg 227301e04c3fSmrg if (!disp->Extensions.KHR_gl_renderbuffer_image) { 227401e04c3fSmrg _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr"); 227501e04c3fSmrg return EGL_NO_IMAGE_KHR; 227601e04c3fSmrg } 22773464ebd5Sriastradh 227801e04c3fSmrg if (dri2_dpy->image->base.version >= 17 && 227901e04c3fSmrg dri2_dpy->image->createImageFromRenderbuffer2) { 228001e04c3fSmrg unsigned error = ~0; 22813464ebd5Sriastradh 228201e04c3fSmrg dri_image = dri2_dpy->image->createImageFromRenderbuffer2( 228301e04c3fSmrg dri2_ctx->dri_context, renderbuffer, NULL, &error); 22843464ebd5Sriastradh 228501e04c3fSmrg assert(!!dri_image == (error == __DRI_IMAGE_ERROR_SUCCESS)); 22863464ebd5Sriastradh 228701e04c3fSmrg if (!dri_image) { 228801e04c3fSmrg _eglError(egl_error_from_dri_image_error(error), "dri2_create_image_khr"); 228901e04c3fSmrg return EGL_NO_IMAGE_KHR; 229001e04c3fSmrg } 229101e04c3fSmrg } else { 229201e04c3fSmrg dri_image = dri2_dpy->image->createImageFromRenderbuffer( 229301e04c3fSmrg dri2_ctx->dri_context, renderbuffer, NULL); 229401e04c3fSmrg if (!dri_image) { 229501e04c3fSmrg _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr"); 229601e04c3fSmrg return EGL_NO_IMAGE_KHR; 229701e04c3fSmrg } 2298cdc920a0Smrg } 2299cdc920a0Smrg 2300af69d88dSmrg return dri2_create_image_from_dri(disp, dri_image); 2301af69d88dSmrg} 2302af69d88dSmrg 2303af69d88dSmrg#ifdef HAVE_WAYLAND_PLATFORM 2304af69d88dSmrg 2305af69d88dSmrg/* This structure describes how a wl_buffer maps to one or more 2306af69d88dSmrg * __DRIimages. A wl_drm_buffer stores the wl_drm format code and the 2307af69d88dSmrg * offsets and strides of the planes in the buffer. This table maps a 2308af69d88dSmrg * wl_drm format code to a description of the planes in the buffer 2309af69d88dSmrg * that lets us create a __DRIimage for each of the planes. */ 2310af69d88dSmrg 2311af69d88dSmrgstatic const struct wl_drm_components_descriptor { 2312af69d88dSmrg uint32_t dri_components; 2313af69d88dSmrg EGLint components; 2314af69d88dSmrg int nplanes; 2315af69d88dSmrg} wl_drm_components[] = { 2316af69d88dSmrg { __DRI_IMAGE_COMPONENTS_RGB, EGL_TEXTURE_RGB, 1 }, 2317af69d88dSmrg { __DRI_IMAGE_COMPONENTS_RGBA, EGL_TEXTURE_RGBA, 1 }, 2318af69d88dSmrg { __DRI_IMAGE_COMPONENTS_Y_U_V, EGL_TEXTURE_Y_U_V_WL, 3 }, 2319af69d88dSmrg { __DRI_IMAGE_COMPONENTS_Y_UV, EGL_TEXTURE_Y_UV_WL, 2 }, 2320af69d88dSmrg { __DRI_IMAGE_COMPONENTS_Y_XUXV, EGL_TEXTURE_Y_XUXV_WL, 2 }, 2321af69d88dSmrg}; 2322af69d88dSmrg 2323af69d88dSmrgstatic _EGLImage * 2324af69d88dSmrgdri2_create_image_wayland_wl_buffer(_EGLDisplay *disp, _EGLContext *ctx, 232501e04c3fSmrg EGLClientBuffer _buffer, 232601e04c3fSmrg const EGLint *attr_list) 2327af69d88dSmrg{ 2328af69d88dSmrg struct wl_drm_buffer *buffer; 2329af69d88dSmrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2330af69d88dSmrg const struct wl_drm_components_descriptor *f; 2331af69d88dSmrg __DRIimage *dri_image; 2332af69d88dSmrg _EGLImageAttribs attrs; 2333af69d88dSmrg int32_t plane; 2334af69d88dSmrg 2335af69d88dSmrg buffer = wayland_drm_buffer_get(dri2_dpy->wl_server_drm, 2336af69d88dSmrg (struct wl_resource *) _buffer); 2337af69d88dSmrg if (!buffer) 2338af69d88dSmrg return NULL; 2339af69d88dSmrg 234001e04c3fSmrg if (!_eglParseImageAttribList(&attrs, disp, attr_list)) 2341af69d88dSmrg return NULL; 2342af69d88dSmrg 234301e04c3fSmrg plane = attrs.PlaneWL; 2344af69d88dSmrg f = buffer->driver_format; 2345af69d88dSmrg if (plane < 0 || plane >= f->nplanes) { 2346af69d88dSmrg _eglError(EGL_BAD_PARAMETER, 2347af69d88dSmrg "dri2_create_image_wayland_wl_buffer (plane out of bounds)"); 2348af69d88dSmrg return NULL; 2349af69d88dSmrg } 2350af69d88dSmrg 2351af69d88dSmrg dri_image = dri2_dpy->image->fromPlanar(buffer->driver_buffer, plane, NULL); 235201e04c3fSmrg if (dri_image == NULL && plane == 0) 235301e04c3fSmrg dri_image = dri2_dpy->image->dupImage(buffer->driver_buffer, NULL); 2354af69d88dSmrg if (dri_image == NULL) { 2355af69d88dSmrg _eglError(EGL_BAD_PARAMETER, "dri2_create_image_wayland_wl_buffer"); 2356af69d88dSmrg return NULL; 2357af69d88dSmrg } 2358af69d88dSmrg 2359af69d88dSmrg return dri2_create_image_from_dri(disp, dri_image); 2360af69d88dSmrg} 2361af69d88dSmrg#endif 2362af69d88dSmrg 2363af69d88dSmrgstatic EGLBoolean 23647e102996Smayadri2_get_sync_values_chromium(_EGLDisplay *disp, _EGLSurface *surf, 2365af69d88dSmrg EGLuint64KHR *ust, EGLuint64KHR *msc, 2366af69d88dSmrg EGLuint64KHR *sbc) 2367af69d88dSmrg{ 23687e102996Smaya struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 23697ec681f3Smrg if (!dri2_dpy->vtbl->get_sync_values) 23707ec681f3Smrg return EGL_FALSE; 23717e102996Smaya return dri2_dpy->vtbl->get_sync_values(disp, surf, ust, msc, sbc); 2372af69d88dSmrg} 2373af69d88dSmrg 2374af69d88dSmrg/** 2375af69d88dSmrg * Set the error code after a call to 2376af69d88dSmrg * dri2_egl_image::dri_image::createImageFromTexture. 2377af69d88dSmrg */ 2378af69d88dSmrgstatic void 2379af69d88dSmrgdri2_create_image_khr_texture_error(int dri_error) 2380af69d88dSmrg{ 238101e04c3fSmrg EGLint egl_error = egl_error_from_dri_image_error(dri_error); 2382af69d88dSmrg 238301e04c3fSmrg if (egl_error != EGL_SUCCESS) 238401e04c3fSmrg _eglError(egl_error, "dri2_create_image_khr_texture"); 238501e04c3fSmrg} 2386af69d88dSmrg 2387af69d88dSmrgstatic _EGLImage * 2388af69d88dSmrgdri2_create_image_khr_texture(_EGLDisplay *disp, _EGLContext *ctx, 238901e04c3fSmrg EGLenum target, 239001e04c3fSmrg EGLClientBuffer buffer, 239101e04c3fSmrg const EGLint *attr_list) 2392af69d88dSmrg{ 2393af69d88dSmrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2394af69d88dSmrg struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); 2395af69d88dSmrg struct dri2_egl_image *dri2_img; 2396af69d88dSmrg GLuint texture = (GLuint) (uintptr_t) buffer; 2397af69d88dSmrg _EGLImageAttribs attrs; 2398af69d88dSmrg GLuint depth; 2399af69d88dSmrg GLenum gl_target; 2400af69d88dSmrg unsigned error; 2401af69d88dSmrg 2402af69d88dSmrg if (texture == 0) { 2403af69d88dSmrg _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr"); 2404af69d88dSmrg return EGL_NO_IMAGE_KHR; 2405af69d88dSmrg } 2406af69d88dSmrg 240701e04c3fSmrg if (!_eglParseImageAttribList(&attrs, disp, attr_list)) 2408af69d88dSmrg return EGL_NO_IMAGE_KHR; 2409af69d88dSmrg 2410af69d88dSmrg switch (target) { 2411af69d88dSmrg case EGL_GL_TEXTURE_2D_KHR: 241201e04c3fSmrg if (!disp->Extensions.KHR_gl_texture_2D_image) { 241301e04c3fSmrg _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr"); 241401e04c3fSmrg return EGL_NO_IMAGE_KHR; 241501e04c3fSmrg } 2416af69d88dSmrg depth = 0; 2417af69d88dSmrg gl_target = GL_TEXTURE_2D; 2418af69d88dSmrg break; 2419af69d88dSmrg case EGL_GL_TEXTURE_3D_KHR: 242001e04c3fSmrg if (!disp->Extensions.KHR_gl_texture_3D_image) { 242101e04c3fSmrg _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr"); 242201e04c3fSmrg return EGL_NO_IMAGE_KHR; 242301e04c3fSmrg } 242401e04c3fSmrg 2425af69d88dSmrg depth = attrs.GLTextureZOffset; 2426af69d88dSmrg gl_target = GL_TEXTURE_3D; 2427af69d88dSmrg break; 2428af69d88dSmrg case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR: 2429af69d88dSmrg case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR: 2430af69d88dSmrg case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR: 2431af69d88dSmrg case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR: 2432af69d88dSmrg case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR: 2433af69d88dSmrg case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR: 243401e04c3fSmrg if (!disp->Extensions.KHR_gl_texture_cubemap_image) { 243501e04c3fSmrg _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr"); 243601e04c3fSmrg return EGL_NO_IMAGE_KHR; 243701e04c3fSmrg } 243801e04c3fSmrg 2439af69d88dSmrg depth = target - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR; 2440af69d88dSmrg gl_target = GL_TEXTURE_CUBE_MAP; 2441af69d88dSmrg break; 2442af69d88dSmrg default: 244301e04c3fSmrg unreachable("Unexpected target in dri2_create_image_khr_texture()"); 2444af69d88dSmrg return EGL_NO_IMAGE_KHR; 2445af69d88dSmrg } 2446af69d88dSmrg 2447cdc920a0Smrg dri2_img = malloc(sizeof *dri2_img); 2448cdc920a0Smrg if (!dri2_img) { 2449af69d88dSmrg _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr"); 2450af69d88dSmrg return EGL_NO_IMAGE_KHR; 2451cdc920a0Smrg } 2452cdc920a0Smrg 245301e04c3fSmrg _eglInitImage(&dri2_img->base, disp); 2454cdc920a0Smrg 2455cdc920a0Smrg dri2_img->dri_image = 2456af69d88dSmrg dri2_dpy->image->createImageFromTexture(dri2_ctx->dri_context, 2457af69d88dSmrg gl_target, 2458af69d88dSmrg texture, 2459af69d88dSmrg depth, 2460af69d88dSmrg attrs.GLTextureLevel, 2461af69d88dSmrg &error, 24627ec681f3Smrg NULL); 2463af69d88dSmrg dri2_create_image_khr_texture_error(error); 2464af69d88dSmrg 2465af69d88dSmrg if (!dri2_img->dri_image) { 24663464ebd5Sriastradh free(dri2_img); 2467af69d88dSmrg return EGL_NO_IMAGE_KHR; 24683464ebd5Sriastradh } 2469cdc920a0Smrg return &dri2_img->base; 2470cdc920a0Smrg} 2471cdc920a0Smrg 247201e04c3fSmrgstatic EGLBoolean 24737ec681f3Smrgdri2_query_surface(_EGLDisplay *disp, _EGLSurface *surf, 247401e04c3fSmrg EGLint attribute, EGLint *value) 247501e04c3fSmrg{ 24767e102996Smaya struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 247701e04c3fSmrg if (!dri2_dpy->vtbl->query_surface) 24787ec681f3Smrg return _eglQuerySurface(disp, surf, attribute, value); 24797ec681f3Smrg return dri2_dpy->vtbl->query_surface(disp, surf, attribute, value); 248001e04c3fSmrg} 248101e04c3fSmrg 2482af69d88dSmrgstatic struct wl_buffer* 24837ec681f3Smrgdri2_create_wayland_buffer_from_image(_EGLDisplay *disp, _EGLImage *img) 2484cdc920a0Smrg{ 24857e102996Smaya struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 24867ec681f3Smrg if (!dri2_dpy->vtbl->create_wayland_buffer_from_image) 24877ec681f3Smrg return NULL; 24887ec681f3Smrg return dri2_dpy->vtbl->create_wayland_buffer_from_image(disp, img); 2489af69d88dSmrg} 2490cdc920a0Smrg 249101e04c3fSmrg#ifdef HAVE_LIBDRM 249201e04c3fSmrgstatic _EGLImage * 249301e04c3fSmrgdri2_create_image_mesa_drm_buffer(_EGLDisplay *disp, _EGLContext *ctx, 249401e04c3fSmrg EGLClientBuffer buffer, const EGLint *attr_list) 249501e04c3fSmrg{ 249601e04c3fSmrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 249701e04c3fSmrg EGLint format, name, pitch; 249801e04c3fSmrg _EGLImageAttribs attrs; 249901e04c3fSmrg __DRIimage *dri_image; 250001e04c3fSmrg 250101e04c3fSmrg name = (EGLint) (uintptr_t) buffer; 250201e04c3fSmrg 250301e04c3fSmrg if (!_eglParseImageAttribList(&attrs, disp, attr_list)) 250401e04c3fSmrg return NULL; 250501e04c3fSmrg 250601e04c3fSmrg if (attrs.Width <= 0 || attrs.Height <= 0 || 250701e04c3fSmrg attrs.DRMBufferStrideMESA <= 0) { 250801e04c3fSmrg _eglError(EGL_BAD_PARAMETER, 250901e04c3fSmrg "bad width, height or stride"); 251001e04c3fSmrg return NULL; 251101e04c3fSmrg } 251201e04c3fSmrg 251301e04c3fSmrg switch (attrs.DRMBufferFormatMESA) { 251401e04c3fSmrg case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA: 251501e04c3fSmrg format = __DRI_IMAGE_FORMAT_ARGB8888; 251601e04c3fSmrg pitch = attrs.DRMBufferStrideMESA; 251701e04c3fSmrg break; 251801e04c3fSmrg default: 251901e04c3fSmrg _eglError(EGL_BAD_PARAMETER, 252001e04c3fSmrg "dri2_create_image_khr: unsupported pixmap depth"); 252101e04c3fSmrg return NULL; 252201e04c3fSmrg } 252301e04c3fSmrg 252401e04c3fSmrg dri_image = 252501e04c3fSmrg dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen, 252601e04c3fSmrg attrs.Width, 252701e04c3fSmrg attrs.Height, 252801e04c3fSmrg format, 252901e04c3fSmrg name, 253001e04c3fSmrg pitch, 253101e04c3fSmrg NULL); 253201e04c3fSmrg 253301e04c3fSmrg return dri2_create_image_from_dri(disp, dri_image); 253401e04c3fSmrg} 253501e04c3fSmrg 2536af69d88dSmrgstatic EGLBoolean 2537af69d88dSmrgdri2_check_dma_buf_attribs(const _EGLImageAttribs *attrs) 2538af69d88dSmrg{ 2539af69d88dSmrg /** 2540af69d88dSmrg * The spec says: 2541af69d88dSmrg * 2542af69d88dSmrg * "Required attributes and their values are as follows: 2543af69d88dSmrg * 2544af69d88dSmrg * * EGL_WIDTH & EGL_HEIGHT: The logical dimensions of the buffer in pixels 2545af69d88dSmrg * 2546af69d88dSmrg * * EGL_LINUX_DRM_FOURCC_EXT: The pixel format of the buffer, as specified 2547af69d88dSmrg * by drm_fourcc.h and used as the pixel_format parameter of the 2548af69d88dSmrg * drm_mode_fb_cmd2 ioctl." 2549af69d88dSmrg * 2550af69d88dSmrg * and 2551af69d88dSmrg * 2552af69d88dSmrg * "* If <target> is EGL_LINUX_DMA_BUF_EXT, and the list of attributes is 2553af69d88dSmrg * incomplete, EGL_BAD_PARAMETER is generated." 2554af69d88dSmrg */ 2555af69d88dSmrg if (attrs->Width <= 0 || attrs->Height <= 0 || 255601e04c3fSmrg !attrs->DMABufFourCC.IsPresent) 255701e04c3fSmrg return _eglError(EGL_BAD_PARAMETER, "attribute(s) missing"); 2558af69d88dSmrg 2559af69d88dSmrg /** 2560af69d88dSmrg * Also: 2561af69d88dSmrg * 2562af69d88dSmrg * "If <target> is EGL_LINUX_DMA_BUF_EXT and one or more of the values 2563af69d88dSmrg * specified for a plane's pitch or offset isn't supported by EGL, 2564af69d88dSmrg * EGL_BAD_ACCESS is generated." 2565af69d88dSmrg */ 256601e04c3fSmrg for (unsigned i = 0; i < ARRAY_SIZE(attrs->DMABufPlanePitches); ++i) { 2567af69d88dSmrg if (attrs->DMABufPlanePitches[i].IsPresent && 256801e04c3fSmrg attrs->DMABufPlanePitches[i].Value <= 0) 256901e04c3fSmrg return _eglError(EGL_BAD_ACCESS, "invalid pitch"); 257001e04c3fSmrg } 257101e04c3fSmrg 257201e04c3fSmrg /** 257301e04c3fSmrg * If <target> is EGL_LINUX_DMA_BUF_EXT, both or neither of the following 257401e04c3fSmrg * attribute values may be given. 257501e04c3fSmrg * 257601e04c3fSmrg * This is referring to EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT and 257701e04c3fSmrg * EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT, and the same for other planes. 257801e04c3fSmrg */ 257901e04c3fSmrg for (unsigned i = 0; i < DMA_BUF_MAX_PLANES; ++i) { 258001e04c3fSmrg if (attrs->DMABufPlaneModifiersLo[i].IsPresent != 258101e04c3fSmrg attrs->DMABufPlaneModifiersHi[i].IsPresent) 258201e04c3fSmrg return _eglError(EGL_BAD_PARAMETER, "modifier attribute lo or hi missing"); 258301e04c3fSmrg } 258401e04c3fSmrg 258501e04c3fSmrg /* Although the EGL_EXT_image_dma_buf_import_modifiers spec doesn't 258601e04c3fSmrg * mandate it, we only accept the same modifier across all planes. */ 258701e04c3fSmrg for (unsigned i = 1; i < DMA_BUF_MAX_PLANES; ++i) { 258801e04c3fSmrg if (attrs->DMABufPlaneFds[i].IsPresent) { 258901e04c3fSmrg if ((attrs->DMABufPlaneModifiersLo[0].IsPresent != 259001e04c3fSmrg attrs->DMABufPlaneModifiersLo[i].IsPresent) || 259101e04c3fSmrg (attrs->DMABufPlaneModifiersLo[0].Value != 259201e04c3fSmrg attrs->DMABufPlaneModifiersLo[i].Value) || 259301e04c3fSmrg (attrs->DMABufPlaneModifiersHi[0].Value != 259401e04c3fSmrg attrs->DMABufPlaneModifiersHi[i].Value)) 259501e04c3fSmrg return _eglError(EGL_BAD_PARAMETER, "modifier attributes not equal"); 2596af69d88dSmrg } 2597af69d88dSmrg } 2598cdc920a0Smrg 2599af69d88dSmrg return EGL_TRUE; 26003464ebd5Sriastradh} 2601cdc920a0Smrg 260201e04c3fSmrg/* Returns the total number of planes for the format or zero if it isn't a 260301e04c3fSmrg * valid fourcc format. 260401e04c3fSmrg */ 2605af69d88dSmrgstatic unsigned 260601e04c3fSmrgdri2_num_fourcc_format_planes(EGLint format) 2607af69d88dSmrg{ 260801e04c3fSmrg switch (format) { 260901e04c3fSmrg case DRM_FORMAT_R8: 261001e04c3fSmrg case DRM_FORMAT_RG88: 261101e04c3fSmrg case DRM_FORMAT_GR88: 261201e04c3fSmrg case DRM_FORMAT_R16: 261301e04c3fSmrg case DRM_FORMAT_GR1616: 2614af69d88dSmrg case DRM_FORMAT_RGB332: 2615af69d88dSmrg case DRM_FORMAT_BGR233: 2616af69d88dSmrg case DRM_FORMAT_XRGB4444: 2617af69d88dSmrg case DRM_FORMAT_XBGR4444: 2618af69d88dSmrg case DRM_FORMAT_RGBX4444: 2619af69d88dSmrg case DRM_FORMAT_BGRX4444: 2620af69d88dSmrg case DRM_FORMAT_ARGB4444: 2621af69d88dSmrg case DRM_FORMAT_ABGR4444: 2622af69d88dSmrg case DRM_FORMAT_RGBA4444: 2623af69d88dSmrg case DRM_FORMAT_BGRA4444: 2624af69d88dSmrg case DRM_FORMAT_XRGB1555: 2625af69d88dSmrg case DRM_FORMAT_XBGR1555: 2626af69d88dSmrg case DRM_FORMAT_RGBX5551: 2627af69d88dSmrg case DRM_FORMAT_BGRX5551: 2628af69d88dSmrg case DRM_FORMAT_ARGB1555: 2629af69d88dSmrg case DRM_FORMAT_ABGR1555: 2630af69d88dSmrg case DRM_FORMAT_RGBA5551: 2631af69d88dSmrg case DRM_FORMAT_BGRA5551: 2632af69d88dSmrg case DRM_FORMAT_RGB565: 2633af69d88dSmrg case DRM_FORMAT_BGR565: 2634af69d88dSmrg case DRM_FORMAT_RGB888: 2635af69d88dSmrg case DRM_FORMAT_BGR888: 2636af69d88dSmrg case DRM_FORMAT_XRGB8888: 2637af69d88dSmrg case DRM_FORMAT_XBGR8888: 2638af69d88dSmrg case DRM_FORMAT_RGBX8888: 2639af69d88dSmrg case DRM_FORMAT_BGRX8888: 2640af69d88dSmrg case DRM_FORMAT_ARGB8888: 2641af69d88dSmrg case DRM_FORMAT_ABGR8888: 2642af69d88dSmrg case DRM_FORMAT_RGBA8888: 2643af69d88dSmrg case DRM_FORMAT_BGRA8888: 2644af69d88dSmrg case DRM_FORMAT_XRGB2101010: 2645af69d88dSmrg case DRM_FORMAT_XBGR2101010: 2646af69d88dSmrg case DRM_FORMAT_RGBX1010102: 2647af69d88dSmrg case DRM_FORMAT_BGRX1010102: 2648af69d88dSmrg case DRM_FORMAT_ARGB2101010: 2649af69d88dSmrg case DRM_FORMAT_ABGR2101010: 2650af69d88dSmrg case DRM_FORMAT_RGBA1010102: 2651af69d88dSmrg case DRM_FORMAT_BGRA1010102: 26527ec681f3Smrg case DRM_FORMAT_XBGR16161616F: 26537ec681f3Smrg case DRM_FORMAT_ABGR16161616F: 2654af69d88dSmrg case DRM_FORMAT_YUYV: 2655af69d88dSmrg case DRM_FORMAT_YVYU: 2656af69d88dSmrg case DRM_FORMAT_UYVY: 2657af69d88dSmrg case DRM_FORMAT_VYUY: 26587e102996Smaya case DRM_FORMAT_AYUV: 26597e102996Smaya case DRM_FORMAT_XYUV8888: 26607ec681f3Smrg case DRM_FORMAT_Y210: 26617ec681f3Smrg case DRM_FORMAT_Y212: 26627ec681f3Smrg case DRM_FORMAT_Y216: 26637ec681f3Smrg case DRM_FORMAT_Y410: 26647ec681f3Smrg case DRM_FORMAT_Y412: 26657ec681f3Smrg case DRM_FORMAT_Y416: 266601e04c3fSmrg return 1; 266701e04c3fSmrg 2668af69d88dSmrg case DRM_FORMAT_NV12: 2669af69d88dSmrg case DRM_FORMAT_NV21: 2670af69d88dSmrg case DRM_FORMAT_NV16: 2671af69d88dSmrg case DRM_FORMAT_NV61: 26727e102996Smaya case DRM_FORMAT_P010: 26737e102996Smaya case DRM_FORMAT_P012: 26747e102996Smaya case DRM_FORMAT_P016: 267501e04c3fSmrg return 2; 267601e04c3fSmrg 2677af69d88dSmrg case DRM_FORMAT_YUV410: 2678af69d88dSmrg case DRM_FORMAT_YVU410: 2679af69d88dSmrg case DRM_FORMAT_YUV411: 2680af69d88dSmrg case DRM_FORMAT_YVU411: 2681af69d88dSmrg case DRM_FORMAT_YUV420: 2682af69d88dSmrg case DRM_FORMAT_YVU420: 2683af69d88dSmrg case DRM_FORMAT_YUV422: 2684af69d88dSmrg case DRM_FORMAT_YVU422: 2685af69d88dSmrg case DRM_FORMAT_YUV444: 2686af69d88dSmrg case DRM_FORMAT_YVU444: 268701e04c3fSmrg return 3; 268801e04c3fSmrg 2689af69d88dSmrg default: 269001e04c3fSmrg return 0; 269101e04c3fSmrg } 269201e04c3fSmrg} 269301e04c3fSmrg 269401e04c3fSmrg/* Returns the total number of file descriptors. Zero indicates an error. */ 269501e04c3fSmrgstatic unsigned 269601e04c3fSmrgdri2_check_dma_buf_format(const _EGLImageAttribs *attrs) 269701e04c3fSmrg{ 269801e04c3fSmrg unsigned plane_n = dri2_num_fourcc_format_planes(attrs->DMABufFourCC.Value); 269901e04c3fSmrg if (plane_n == 0) { 270001e04c3fSmrg _eglError(EGL_BAD_MATCH, "unknown drm fourcc format"); 2701af69d88dSmrg return 0; 2702af69d88dSmrg } 2703af69d88dSmrg 270401e04c3fSmrg for (unsigned i = plane_n; i < DMA_BUF_MAX_PLANES; i++) { 270501e04c3fSmrg /** 270601e04c3fSmrg * The modifiers extension spec says: 270701e04c3fSmrg * 270801e04c3fSmrg * "Modifiers may modify any attribute of a buffer import, including 270901e04c3fSmrg * but not limited to adding extra planes to a format which 271001e04c3fSmrg * otherwise does not have those planes. As an example, a modifier 271101e04c3fSmrg * may add a plane for an external compression buffer to a 271201e04c3fSmrg * single-plane format. The exact meaning and effect of any 271301e04c3fSmrg * modifier is canonically defined by drm_fourcc.h, not as part of 271401e04c3fSmrg * this extension." 271501e04c3fSmrg */ 271601e04c3fSmrg if (attrs->DMABufPlaneModifiersLo[i].IsPresent && 271701e04c3fSmrg attrs->DMABufPlaneModifiersHi[i].IsPresent) { 271801e04c3fSmrg plane_n = i + 1; 271901e04c3fSmrg } 272001e04c3fSmrg } 272101e04c3fSmrg 2722af69d88dSmrg /** 2723af69d88dSmrg * The spec says: 2724af69d88dSmrg * 2725af69d88dSmrg * "* If <target> is EGL_LINUX_DMA_BUF_EXT, and the list of attributes is 2726af69d88dSmrg * incomplete, EGL_BAD_PARAMETER is generated." 2727af69d88dSmrg */ 272801e04c3fSmrg for (unsigned i = 0; i < plane_n; ++i) { 2729af69d88dSmrg if (!attrs->DMABufPlaneFds[i].IsPresent || 2730af69d88dSmrg !attrs->DMABufPlaneOffsets[i].IsPresent || 2731af69d88dSmrg !attrs->DMABufPlanePitches[i].IsPresent) { 2732af69d88dSmrg _eglError(EGL_BAD_PARAMETER, "plane attribute(s) missing"); 2733af69d88dSmrg return 0; 2734af69d88dSmrg } 2735af69d88dSmrg } 2736af69d88dSmrg 2737af69d88dSmrg /** 2738af69d88dSmrg * The spec also says: 2739af69d88dSmrg * 2740af69d88dSmrg * "If <target> is EGL_LINUX_DMA_BUF_EXT, and the EGL_LINUX_DRM_FOURCC_EXT 2741af69d88dSmrg * attribute indicates a single-plane format, EGL_BAD_ATTRIBUTE is 2742af69d88dSmrg * generated if any of the EGL_DMA_BUF_PLANE1_* or EGL_DMA_BUF_PLANE2_* 274301e04c3fSmrg * or EGL_DMA_BUF_PLANE3_* attributes are specified." 2744af69d88dSmrg */ 274501e04c3fSmrg for (unsigned i = plane_n; i < DMA_BUF_MAX_PLANES; ++i) { 2746af69d88dSmrg if (attrs->DMABufPlaneFds[i].IsPresent || 2747af69d88dSmrg attrs->DMABufPlaneOffsets[i].IsPresent || 2748af69d88dSmrg attrs->DMABufPlanePitches[i].IsPresent) { 2749af69d88dSmrg _eglError(EGL_BAD_ATTRIBUTE, "too many plane attributes"); 2750af69d88dSmrg return 0; 2751af69d88dSmrg } 2752af69d88dSmrg } 2753af69d88dSmrg 2754af69d88dSmrg return plane_n; 2755af69d88dSmrg} 2756af69d88dSmrg 275701e04c3fSmrgstatic EGLBoolean 27587ec681f3Smrgdri2_query_dma_buf_formats(_EGLDisplay *disp, EGLint max, 27597ec681f3Smrg EGLint *formats, EGLint *count) 276001e04c3fSmrg{ 276101e04c3fSmrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 276201e04c3fSmrg if (max < 0 || (max > 0 && formats == NULL)) 276301e04c3fSmrg return _eglError(EGL_BAD_PARAMETER, "invalid value for max count of formats"); 276401e04c3fSmrg 276501e04c3fSmrg if (dri2_dpy->image->base.version < 15 || 276601e04c3fSmrg dri2_dpy->image->queryDmaBufFormats == NULL) 276701e04c3fSmrg return EGL_FALSE; 276801e04c3fSmrg 276901e04c3fSmrg if (!dri2_dpy->image->queryDmaBufFormats(dri2_dpy->dri_screen, max, 277001e04c3fSmrg formats, count)) 277101e04c3fSmrg return EGL_FALSE; 277201e04c3fSmrg 277301e04c3fSmrg if (max > 0) { 277401e04c3fSmrg /* Assert that all of the formats returned are actually fourcc formats. 277501e04c3fSmrg * Some day, if we want the internal interface function to be able to 277601e04c3fSmrg * return the fake fourcc formats defined in dri_interface.h, we'll have 277701e04c3fSmrg * to do something more clever here to pair the list down to just real 277801e04c3fSmrg * fourcc formats so that we don't leak the fake internal ones. 277901e04c3fSmrg */ 278001e04c3fSmrg for (int i = 0; i < *count; i++) { 278101e04c3fSmrg assert(dri2_num_fourcc_format_planes(formats[i]) > 0); 278201e04c3fSmrg } 278301e04c3fSmrg } 278401e04c3fSmrg 278501e04c3fSmrg return EGL_TRUE; 278601e04c3fSmrg} 278701e04c3fSmrg 278801e04c3fSmrgstatic EGLBoolean 27897ec681f3Smrgdri2_query_dma_buf_modifiers(_EGLDisplay *disp, EGLint format, 279001e04c3fSmrg EGLint max, EGLuint64KHR *modifiers, 279101e04c3fSmrg EGLBoolean *external_only, EGLint *count) 279201e04c3fSmrg{ 279301e04c3fSmrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 279401e04c3fSmrg 279501e04c3fSmrg if (dri2_num_fourcc_format_planes(format) == 0) 279601e04c3fSmrg return _eglError(EGL_BAD_PARAMETER, "invalid fourcc format"); 279701e04c3fSmrg 279801e04c3fSmrg if (max < 0) 279901e04c3fSmrg return _eglError(EGL_BAD_PARAMETER, "invalid value for max count of formats"); 280001e04c3fSmrg 280101e04c3fSmrg if (max > 0 && modifiers == NULL) 280201e04c3fSmrg return _eglError(EGL_BAD_PARAMETER, "invalid modifiers array"); 280301e04c3fSmrg 280401e04c3fSmrg if (dri2_dpy->image->base.version < 15 || 280501e04c3fSmrg dri2_dpy->image->queryDmaBufModifiers == NULL) 280601e04c3fSmrg return EGL_FALSE; 280701e04c3fSmrg 280801e04c3fSmrg if (dri2_dpy->image->queryDmaBufModifiers(dri2_dpy->dri_screen, format, 280901e04c3fSmrg max, modifiers, 281001e04c3fSmrg (unsigned int *) external_only, 281101e04c3fSmrg count) == false) 281201e04c3fSmrg return _eglError(EGL_BAD_PARAMETER, "invalid format"); 281301e04c3fSmrg 281401e04c3fSmrg return EGL_TRUE; 281501e04c3fSmrg} 281601e04c3fSmrg 2817af69d88dSmrg/** 2818af69d88dSmrg * The spec says: 2819af69d88dSmrg * 2820af69d88dSmrg * "If eglCreateImageKHR is successful for a EGL_LINUX_DMA_BUF_EXT target, the 2821af69d88dSmrg * EGL will take a reference to the dma_buf(s) which it will release at any 2822af69d88dSmrg * time while the EGLDisplay is initialized. It is the responsibility of the 2823af69d88dSmrg * application to close the dma_buf file descriptors." 2824af69d88dSmrg * 2825af69d88dSmrg * Therefore we must never close or otherwise modify the file descriptors. 2826af69d88dSmrg */ 282701e04c3fSmrg_EGLImage * 2828af69d88dSmrgdri2_create_image_dma_buf(_EGLDisplay *disp, _EGLContext *ctx, 282901e04c3fSmrg EGLClientBuffer buffer, const EGLint *attr_list) 28303464ebd5Sriastradh{ 2831af69d88dSmrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2832af69d88dSmrg _EGLImage *res; 2833af69d88dSmrg _EGLImageAttribs attrs; 2834af69d88dSmrg __DRIimage *dri_image; 2835af69d88dSmrg unsigned num_fds; 283601e04c3fSmrg int fds[DMA_BUF_MAX_PLANES]; 283701e04c3fSmrg int pitches[DMA_BUF_MAX_PLANES]; 283801e04c3fSmrg int offsets[DMA_BUF_MAX_PLANES]; 283901e04c3fSmrg uint64_t modifier; 284001e04c3fSmrg bool has_modifier = false; 2841af69d88dSmrg unsigned error; 2842af69d88dSmrg 2843af69d88dSmrg /** 2844af69d88dSmrg * The spec says: 2845af69d88dSmrg * 2846af69d88dSmrg * ""* If <target> is EGL_LINUX_DMA_BUF_EXT and <buffer> is not NULL, the 2847af69d88dSmrg * error EGL_BAD_PARAMETER is generated." 2848af69d88dSmrg */ 2849af69d88dSmrg if (buffer != NULL) { 2850af69d88dSmrg _eglError(EGL_BAD_PARAMETER, "buffer not NULL"); 2851af69d88dSmrg return NULL; 2852af69d88dSmrg } 2853cdc920a0Smrg 285401e04c3fSmrg if (!_eglParseImageAttribList(&attrs, disp, attr_list)) 2855af69d88dSmrg return NULL; 2856af69d88dSmrg 2857af69d88dSmrg if (!dri2_check_dma_buf_attribs(&attrs)) 2858af69d88dSmrg return NULL; 2859af69d88dSmrg 2860af69d88dSmrg num_fds = dri2_check_dma_buf_format(&attrs); 2861af69d88dSmrg if (!num_fds) 2862af69d88dSmrg return NULL; 2863af69d88dSmrg 286401e04c3fSmrg for (unsigned i = 0; i < num_fds; ++i) { 2865af69d88dSmrg fds[i] = attrs.DMABufPlaneFds[i].Value; 2866af69d88dSmrg pitches[i] = attrs.DMABufPlanePitches[i].Value; 2867af69d88dSmrg offsets[i] = attrs.DMABufPlaneOffsets[i].Value; 2868af69d88dSmrg } 2869af69d88dSmrg 287001e04c3fSmrg /* dri2_check_dma_buf_attribs ensures that the modifier, if available, 287101e04c3fSmrg * will be present in attrs.DMABufPlaneModifiersLo[0] and 287201e04c3fSmrg * attrs.DMABufPlaneModifiersHi[0] */ 287301e04c3fSmrg if (attrs.DMABufPlaneModifiersLo[0].IsPresent) { 287401e04c3fSmrg modifier = combine_u32_into_u64(attrs.DMABufPlaneModifiersHi[0].Value, 287501e04c3fSmrg attrs.DMABufPlaneModifiersLo[0].Value); 287601e04c3fSmrg has_modifier = true; 287701e04c3fSmrg } 287801e04c3fSmrg 28797ec681f3Smrg if (attrs.ProtectedContent) { 28807ec681f3Smrg if (dri2_dpy->image->base.version < 18 || 28817ec681f3Smrg dri2_dpy->image->createImageFromDmaBufs3 == NULL) { 28827ec681f3Smrg _eglError(EGL_BAD_MATCH, "unsupported protected_content attribute"); 28837ec681f3Smrg return EGL_NO_IMAGE_KHR; 28847ec681f3Smrg } 28857ec681f3Smrg if (!has_modifier) 28867ec681f3Smrg modifier = DRM_FORMAT_MOD_INVALID; 28877ec681f3Smrg 28887ec681f3Smrg dri_image = 28897ec681f3Smrg dri2_dpy->image->createImageFromDmaBufs3(dri2_dpy->dri_screen, 28907ec681f3Smrg attrs.Width, attrs.Height, attrs.DMABufFourCC.Value, 28917ec681f3Smrg modifier, fds, num_fds, pitches, offsets, 28927ec681f3Smrg attrs.DMABufYuvColorSpaceHint.Value, 28937ec681f3Smrg attrs.DMABufSampleRangeHint.Value, 28947ec681f3Smrg attrs.DMABufChromaHorizontalSiting.Value, 28957ec681f3Smrg attrs.DMABufChromaVerticalSiting.Value, 28967ec681f3Smrg attrs.ProtectedContent ? __DRI_IMAGE_PROTECTED_CONTENT_FLAG : 0, 28977ec681f3Smrg &error, 28987ec681f3Smrg NULL); 28997ec681f3Smrg } 29007ec681f3Smrg else if (has_modifier) { 290101e04c3fSmrg if (dri2_dpy->image->base.version < 15 || 290201e04c3fSmrg dri2_dpy->image->createImageFromDmaBufs2 == NULL) { 290301e04c3fSmrg _eglError(EGL_BAD_MATCH, "unsupported dma_buf format modifier"); 290401e04c3fSmrg return EGL_NO_IMAGE_KHR; 290501e04c3fSmrg } 290601e04c3fSmrg dri_image = 290701e04c3fSmrg dri2_dpy->image->createImageFromDmaBufs2(dri2_dpy->dri_screen, 290801e04c3fSmrg attrs.Width, attrs.Height, attrs.DMABufFourCC.Value, 290901e04c3fSmrg modifier, fds, num_fds, pitches, offsets, 291001e04c3fSmrg attrs.DMABufYuvColorSpaceHint.Value, 291101e04c3fSmrg attrs.DMABufSampleRangeHint.Value, 291201e04c3fSmrg attrs.DMABufChromaHorizontalSiting.Value, 291301e04c3fSmrg attrs.DMABufChromaVerticalSiting.Value, 291401e04c3fSmrg &error, 291501e04c3fSmrg NULL); 291601e04c3fSmrg } 291701e04c3fSmrg else { 291801e04c3fSmrg dri_image = 291901e04c3fSmrg dri2_dpy->image->createImageFromDmaBufs(dri2_dpy->dri_screen, 292001e04c3fSmrg attrs.Width, attrs.Height, attrs.DMABufFourCC.Value, 292101e04c3fSmrg fds, num_fds, pitches, offsets, 292201e04c3fSmrg attrs.DMABufYuvColorSpaceHint.Value, 292301e04c3fSmrg attrs.DMABufSampleRangeHint.Value, 292401e04c3fSmrg attrs.DMABufChromaHorizontalSiting.Value, 292501e04c3fSmrg attrs.DMABufChromaVerticalSiting.Value, 292601e04c3fSmrg &error, 292701e04c3fSmrg NULL); 292801e04c3fSmrg } 2929af69d88dSmrg dri2_create_image_khr_texture_error(error); 2930af69d88dSmrg 2931af69d88dSmrg if (!dri_image) 2932af69d88dSmrg return EGL_NO_IMAGE_KHR; 2933cdc920a0Smrg 2934af69d88dSmrg res = dri2_create_image_from_dri(disp, dri_image); 2935af69d88dSmrg 2936af69d88dSmrg return res; 2937cdc920a0Smrg} 29383464ebd5Sriastradhstatic _EGLImage * 29397ec681f3Smrgdri2_create_drm_image_mesa(_EGLDisplay *disp, const EGLint *attr_list) 29403464ebd5Sriastradh{ 29413464ebd5Sriastradh struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 29423464ebd5Sriastradh struct dri2_egl_image *dri2_img; 29433464ebd5Sriastradh _EGLImageAttribs attrs; 29443464ebd5Sriastradh unsigned int dri_use, valid_mask; 29453464ebd5Sriastradh int format; 29463464ebd5Sriastradh 29473464ebd5Sriastradh if (!attr_list) { 294801e04c3fSmrg _eglError(EGL_BAD_PARAMETER, __func__); 294901e04c3fSmrg return EGL_NO_IMAGE_KHR; 29503464ebd5Sriastradh } 29513464ebd5Sriastradh 295201e04c3fSmrg if (!_eglParseImageAttribList(&attrs, disp, attr_list)) 295301e04c3fSmrg return EGL_NO_IMAGE_KHR; 29543464ebd5Sriastradh 29553464ebd5Sriastradh if (attrs.Width <= 0 || attrs.Height <= 0) { 295601e04c3fSmrg _eglError(EGL_BAD_PARAMETER, __func__); 295701e04c3fSmrg return EGL_NO_IMAGE_KHR; 29583464ebd5Sriastradh } 29593464ebd5Sriastradh 29603464ebd5Sriastradh switch (attrs.DRMBufferFormatMESA) { 29613464ebd5Sriastradh case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA: 29623464ebd5Sriastradh format = __DRI_IMAGE_FORMAT_ARGB8888; 29633464ebd5Sriastradh break; 29643464ebd5Sriastradh default: 296501e04c3fSmrg _eglError(EGL_BAD_PARAMETER, __func__); 296601e04c3fSmrg return EGL_NO_IMAGE_KHR; 29673464ebd5Sriastradh } 29683464ebd5Sriastradh 29693464ebd5Sriastradh valid_mask = 29703464ebd5Sriastradh EGL_DRM_BUFFER_USE_SCANOUT_MESA | 29713464ebd5Sriastradh EGL_DRM_BUFFER_USE_SHARE_MESA | 29723464ebd5Sriastradh EGL_DRM_BUFFER_USE_CURSOR_MESA; 29733464ebd5Sriastradh if (attrs.DRMBufferUseMESA & ~valid_mask) { 297401e04c3fSmrg _eglError(EGL_BAD_PARAMETER, __func__); 297501e04c3fSmrg return EGL_NO_IMAGE_KHR; 29763464ebd5Sriastradh } 29773464ebd5Sriastradh 29783464ebd5Sriastradh dri_use = 0; 29793464ebd5Sriastradh if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SHARE_MESA) 29803464ebd5Sriastradh dri_use |= __DRI_IMAGE_USE_SHARE; 29813464ebd5Sriastradh if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SCANOUT_MESA) 29823464ebd5Sriastradh dri_use |= __DRI_IMAGE_USE_SCANOUT; 29833464ebd5Sriastradh if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_CURSOR_MESA) 29843464ebd5Sriastradh dri_use |= __DRI_IMAGE_USE_CURSOR; 29853464ebd5Sriastradh 298601e04c3fSmrg dri2_img = malloc(sizeof *dri2_img); 298701e04c3fSmrg if (!dri2_img) { 298801e04c3fSmrg _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr"); 298901e04c3fSmrg return EGL_NO_IMAGE_KHR; 299001e04c3fSmrg } 299101e04c3fSmrg 299201e04c3fSmrg _eglInitImage(&dri2_img->base, disp); 299301e04c3fSmrg 299401e04c3fSmrg dri2_img->dri_image = 29953464ebd5Sriastradh dri2_dpy->image->createImage(dri2_dpy->dri_screen, 299601e04c3fSmrg attrs.Width, attrs.Height, 29973464ebd5Sriastradh format, dri_use, dri2_img); 29983464ebd5Sriastradh if (dri2_img->dri_image == NULL) { 299901e04c3fSmrg free(dri2_img); 300001e04c3fSmrg _eglError(EGL_BAD_ALLOC, "dri2_create_drm_image_mesa"); 300101e04c3fSmrg return EGL_NO_IMAGE_KHR; 30023464ebd5Sriastradh } 30033464ebd5Sriastradh 30043464ebd5Sriastradh return &dri2_img->base; 30053464ebd5Sriastradh} 30063464ebd5Sriastradh 30073464ebd5Sriastradhstatic EGLBoolean 30087ec681f3Smrgdri2_export_drm_image_mesa(_EGLDisplay *disp, _EGLImage *img, 300901e04c3fSmrg EGLint *name, EGLint *handle, EGLint *stride) 30103464ebd5Sriastradh{ 30113464ebd5Sriastradh struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 30123464ebd5Sriastradh struct dri2_egl_image *dri2_img = dri2_egl_image(img); 30133464ebd5Sriastradh 30143464ebd5Sriastradh if (name && !dri2_dpy->image->queryImage(dri2_img->dri_image, 301501e04c3fSmrg __DRI_IMAGE_ATTRIB_NAME, name)) 301601e04c3fSmrg return _eglError(EGL_BAD_ALLOC, "dri2_export_drm_image_mesa"); 30173464ebd5Sriastradh 30183464ebd5Sriastradh if (handle) 30193464ebd5Sriastradh dri2_dpy->image->queryImage(dri2_img->dri_image, 302001e04c3fSmrg __DRI_IMAGE_ATTRIB_HANDLE, handle); 30213464ebd5Sriastradh 30223464ebd5Sriastradh if (stride) 30233464ebd5Sriastradh dri2_dpy->image->queryImage(dri2_img->dri_image, 302401e04c3fSmrg __DRI_IMAGE_ATTRIB_STRIDE, stride); 30253464ebd5Sriastradh 30263464ebd5Sriastradh return EGL_TRUE; 30273464ebd5Sriastradh} 302801e04c3fSmrg 302901e04c3fSmrg/** 303001e04c3fSmrg * Checks if we can support EGL_MESA_image_dma_buf_export on this image. 303101e04c3fSmrg 303201e04c3fSmrg * The spec provides a boolean return for the driver to reject exporting for 303301e04c3fSmrg * basically any reason, but doesn't specify any particular error cases. For 303401e04c3fSmrg * now, we just fail if we don't have a DRM fourcc for the format. 303501e04c3fSmrg */ 303601e04c3fSmrgstatic bool 303701e04c3fSmrgdri2_can_export_dma_buf_image(_EGLDisplay *disp, _EGLImage *img) 303801e04c3fSmrg{ 303901e04c3fSmrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 304001e04c3fSmrg struct dri2_egl_image *dri2_img = dri2_egl_image(img); 304101e04c3fSmrg EGLint fourcc; 304201e04c3fSmrg 304301e04c3fSmrg if (!dri2_dpy->image->queryImage(dri2_img->dri_image, 304401e04c3fSmrg __DRI_IMAGE_ATTRIB_FOURCC, &fourcc)) { 304501e04c3fSmrg return false; 304601e04c3fSmrg } 304701e04c3fSmrg 304801e04c3fSmrg return true; 304901e04c3fSmrg} 305001e04c3fSmrg 305101e04c3fSmrgstatic EGLBoolean 30527ec681f3Smrgdri2_export_dma_buf_image_query_mesa(_EGLDisplay *disp, _EGLImage *img, 305301e04c3fSmrg EGLint *fourcc, EGLint *nplanes, 305401e04c3fSmrg EGLuint64KHR *modifiers) 305501e04c3fSmrg{ 305601e04c3fSmrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 305701e04c3fSmrg struct dri2_egl_image *dri2_img = dri2_egl_image(img); 30587e102996Smaya int num_planes; 305901e04c3fSmrg 306001e04c3fSmrg if (!dri2_can_export_dma_buf_image(disp, img)) 306101e04c3fSmrg return EGL_FALSE; 306201e04c3fSmrg 30637e102996Smaya dri2_dpy->image->queryImage(dri2_img->dri_image, 30647e102996Smaya __DRI_IMAGE_ATTRIB_NUM_PLANES, &num_planes); 306501e04c3fSmrg if (nplanes) 30667e102996Smaya *nplanes = num_planes; 30677e102996Smaya 306801e04c3fSmrg if (fourcc) 306901e04c3fSmrg dri2_dpy->image->queryImage(dri2_img->dri_image, 307001e04c3fSmrg __DRI_IMAGE_ATTRIB_FOURCC, fourcc); 307101e04c3fSmrg 30727e102996Smaya if (modifiers) { 30737e102996Smaya int mod_hi, mod_lo; 30747e102996Smaya uint64_t modifier = DRM_FORMAT_MOD_INVALID; 30757e102996Smaya bool query; 30767e102996Smaya 30777e102996Smaya query = dri2_dpy->image->queryImage(dri2_img->dri_image, 30787e102996Smaya __DRI_IMAGE_ATTRIB_MODIFIER_UPPER, 30797e102996Smaya &mod_hi); 30807e102996Smaya query &= dri2_dpy->image->queryImage(dri2_img->dri_image, 30817e102996Smaya __DRI_IMAGE_ATTRIB_MODIFIER_LOWER, 30827e102996Smaya &mod_lo); 30837e102996Smaya if (query) 30847e102996Smaya modifier = combine_u32_into_u64 (mod_hi, mod_lo); 30857e102996Smaya 30867e102996Smaya for (int i = 0; i < num_planes; i++) 30877e102996Smaya modifiers[i] = modifier; 30887e102996Smaya } 308901e04c3fSmrg 309001e04c3fSmrg return EGL_TRUE; 309101e04c3fSmrg} 309201e04c3fSmrg 309301e04c3fSmrgstatic EGLBoolean 30947ec681f3Smrgdri2_export_dma_buf_image_mesa(_EGLDisplay *disp, _EGLImage *img, 309501e04c3fSmrg int *fds, EGLint *strides, EGLint *offsets) 309601e04c3fSmrg{ 309701e04c3fSmrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 309801e04c3fSmrg struct dri2_egl_image *dri2_img = dri2_egl_image(img); 30997e102996Smaya EGLint nplanes; 310001e04c3fSmrg 310101e04c3fSmrg if (!dri2_can_export_dma_buf_image(disp, img)) 310201e04c3fSmrg return EGL_FALSE; 310301e04c3fSmrg 31047e102996Smaya /* EGL_MESA_image_dma_buf_export spec says: 31057e102996Smaya * "If the number of fds is less than the number of planes, then 31067e102996Smaya * subsequent fd slots should contain -1." 31077e102996Smaya */ 31087e102996Smaya if (fds) { 31097e102996Smaya /* Query nplanes so that we know how big the given array is. */ 31107e102996Smaya dri2_dpy->image->queryImage(dri2_img->dri_image, 31117e102996Smaya __DRI_IMAGE_ATTRIB_NUM_PLANES, &nplanes); 31127e102996Smaya memset(fds, -1, nplanes * sizeof(int)); 31137e102996Smaya } 31147e102996Smaya 311501e04c3fSmrg /* rework later to provide multiple fds/strides/offsets */ 311601e04c3fSmrg if (fds) 311701e04c3fSmrg dri2_dpy->image->queryImage(dri2_img->dri_image, 311801e04c3fSmrg __DRI_IMAGE_ATTRIB_FD, fds); 311901e04c3fSmrg 312001e04c3fSmrg if (strides) 312101e04c3fSmrg dri2_dpy->image->queryImage(dri2_img->dri_image, 312201e04c3fSmrg __DRI_IMAGE_ATTRIB_STRIDE, strides); 312301e04c3fSmrg 312401e04c3fSmrg if (offsets) { 312501e04c3fSmrg int img_offset; 312601e04c3fSmrg bool ret = dri2_dpy->image->queryImage(dri2_img->dri_image, 312701e04c3fSmrg __DRI_IMAGE_ATTRIB_OFFSET, &img_offset); 312801e04c3fSmrg if (ret) 312901e04c3fSmrg offsets[0] = img_offset; 313001e04c3fSmrg else 313101e04c3fSmrg offsets[0] = 0; 313201e04c3fSmrg } 313301e04c3fSmrg 313401e04c3fSmrg return EGL_TRUE; 313501e04c3fSmrg} 313601e04c3fSmrg 3137af69d88dSmrg#endif 31383464ebd5Sriastradh 313901e04c3fSmrg_EGLImage * 31407ec681f3Smrgdri2_create_image_khr(_EGLDisplay *disp, _EGLContext *ctx, EGLenum target, 314101e04c3fSmrg EGLClientBuffer buffer, const EGLint *attr_list) 314201e04c3fSmrg{ 314301e04c3fSmrg switch (target) { 314401e04c3fSmrg case EGL_GL_TEXTURE_2D_KHR: 314501e04c3fSmrg case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR: 314601e04c3fSmrg case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR: 314701e04c3fSmrg case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR: 314801e04c3fSmrg case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR: 314901e04c3fSmrg case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR: 315001e04c3fSmrg case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR: 315101e04c3fSmrg case EGL_GL_TEXTURE_3D_KHR: 315201e04c3fSmrg return dri2_create_image_khr_texture(disp, ctx, target, buffer, attr_list); 315301e04c3fSmrg case EGL_GL_RENDERBUFFER_KHR: 315401e04c3fSmrg return dri2_create_image_khr_renderbuffer(disp, ctx, buffer, attr_list); 315501e04c3fSmrg#ifdef HAVE_LIBDRM 315601e04c3fSmrg case EGL_DRM_BUFFER_MESA: 315701e04c3fSmrg return dri2_create_image_mesa_drm_buffer(disp, ctx, buffer, attr_list); 315801e04c3fSmrg case EGL_LINUX_DMA_BUF_EXT: 315901e04c3fSmrg return dri2_create_image_dma_buf(disp, ctx, buffer, attr_list); 316001e04c3fSmrg#endif 316101e04c3fSmrg#ifdef HAVE_WAYLAND_PLATFORM 316201e04c3fSmrg case EGL_WAYLAND_BUFFER_WL: 316301e04c3fSmrg return dri2_create_image_wayland_wl_buffer(disp, ctx, buffer, attr_list); 316401e04c3fSmrg#endif 316501e04c3fSmrg default: 316601e04c3fSmrg _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr"); 316701e04c3fSmrg return EGL_NO_IMAGE_KHR; 316801e04c3fSmrg } 316901e04c3fSmrg} 317001e04c3fSmrg 317101e04c3fSmrgstatic EGLBoolean 31727ec681f3Smrgdri2_destroy_image_khr(_EGLDisplay *disp, _EGLImage *image) 317301e04c3fSmrg{ 317401e04c3fSmrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 317501e04c3fSmrg struct dri2_egl_image *dri2_img = dri2_egl_image(image); 317601e04c3fSmrg 317701e04c3fSmrg dri2_dpy->image->destroyImage(dri2_img->dri_image); 317801e04c3fSmrg free(dri2_img); 317901e04c3fSmrg 318001e04c3fSmrg return EGL_TRUE; 318101e04c3fSmrg} 318201e04c3fSmrg 31833464ebd5Sriastradh#ifdef HAVE_WAYLAND_PLATFORM 31843464ebd5Sriastradh 3185af69d88dSmrgstatic void 3186af69d88dSmrgdri2_wl_reference_buffer(void *user_data, uint32_t name, int fd, 3187af69d88dSmrg struct wl_drm_buffer *buffer) 31883464ebd5Sriastradh{ 31893464ebd5Sriastradh _EGLDisplay *disp = user_data; 31903464ebd5Sriastradh struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 3191af69d88dSmrg __DRIimage *img; 319201e04c3fSmrg int dri_components = 0; 3193af69d88dSmrg 3194af69d88dSmrg if (fd == -1) 3195af69d88dSmrg img = dri2_dpy->image->createImageFromNames(dri2_dpy->dri_screen, 3196af69d88dSmrg buffer->width, 3197af69d88dSmrg buffer->height, 3198af69d88dSmrg buffer->format, 3199af69d88dSmrg (int*)&name, 1, 3200af69d88dSmrg buffer->stride, 3201af69d88dSmrg buffer->offset, 3202af69d88dSmrg NULL); 3203af69d88dSmrg else 3204af69d88dSmrg img = dri2_dpy->image->createImageFromFds(dri2_dpy->dri_screen, 3205af69d88dSmrg buffer->width, 3206af69d88dSmrg buffer->height, 3207af69d88dSmrg buffer->format, 3208af69d88dSmrg &fd, 1, 3209af69d88dSmrg buffer->stride, 3210af69d88dSmrg buffer->offset, 3211af69d88dSmrg NULL); 3212af69d88dSmrg 3213af69d88dSmrg if (img == NULL) 3214af69d88dSmrg return; 3215af69d88dSmrg 3216af69d88dSmrg dri2_dpy->image->queryImage(img, __DRI_IMAGE_ATTRIB_COMPONENTS, &dri_components); 3217af69d88dSmrg 3218af69d88dSmrg buffer->driver_format = NULL; 321901e04c3fSmrg for (int i = 0; i < ARRAY_SIZE(wl_drm_components); i++) 3220af69d88dSmrg if (wl_drm_components[i].dri_components == dri_components) 3221af69d88dSmrg buffer->driver_format = &wl_drm_components[i]; 3222af69d88dSmrg 3223af69d88dSmrg if (buffer->driver_format == NULL) 3224af69d88dSmrg dri2_dpy->image->destroyImage(img); 3225af69d88dSmrg else 3226af69d88dSmrg buffer->driver_buffer = img; 32273464ebd5Sriastradh} 32283464ebd5Sriastradh 32293464ebd5Sriastradhstatic void 3230af69d88dSmrgdri2_wl_release_buffer(void *user_data, struct wl_drm_buffer *buffer) 32313464ebd5Sriastradh{ 32323464ebd5Sriastradh _EGLDisplay *disp = user_data; 32333464ebd5Sriastradh struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 32343464ebd5Sriastradh 3235af69d88dSmrg dri2_dpy->image->destroyImage(buffer->driver_buffer); 32363464ebd5Sriastradh} 32373464ebd5Sriastradh 32383464ebd5Sriastradhstatic EGLBoolean 32397ec681f3Smrgdri2_bind_wayland_display_wl(_EGLDisplay *disp, struct wl_display *wl_dpy) 32403464ebd5Sriastradh{ 32413464ebd5Sriastradh struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 324201e04c3fSmrg const struct wayland_drm_callbacks wl_drm_callbacks = { 324301e04c3fSmrg .authenticate = (int(*)(void *, uint32_t)) dri2_dpy->vtbl->authenticate, 324401e04c3fSmrg .reference_buffer = dri2_wl_reference_buffer, 324501e04c3fSmrg .release_buffer = dri2_wl_release_buffer, 324601e04c3fSmrg .is_format_supported = dri2_wl_is_format_supported 324701e04c3fSmrg }; 3248af69d88dSmrg int flags = 0; 32497ec681f3Smrg char *device_name; 3250af69d88dSmrg uint64_t cap; 32513464ebd5Sriastradh 32523464ebd5Sriastradh if (dri2_dpy->wl_server_drm) 325301e04c3fSmrg return EGL_FALSE; 32543464ebd5Sriastradh 32557ec681f3Smrg device_name = drmGetRenderDeviceNameFromFd(dri2_dpy->fd); 32567ec681f3Smrg if (!device_name) 32577ec681f3Smrg device_name = strdup(dri2_dpy->device_name); 32587ec681f3Smrg if (!device_name) 32597ec681f3Smrg return EGL_FALSE; 32607ec681f3Smrg 3261af69d88dSmrg if (drmGetCap(dri2_dpy->fd, DRM_CAP_PRIME, &cap) == 0 && 3262af69d88dSmrg cap == (DRM_PRIME_CAP_IMPORT | DRM_PRIME_CAP_EXPORT) && 3263af69d88dSmrg dri2_dpy->image->base.version >= 7 && 3264af69d88dSmrg dri2_dpy->image->createImageFromFds != NULL) 3265af69d88dSmrg flags |= WAYLAND_DRM_PRIME; 32663464ebd5Sriastradh 32673464ebd5Sriastradh dri2_dpy->wl_server_drm = 32687ec681f3Smrg wayland_drm_init(wl_dpy, device_name, 3269af69d88dSmrg &wl_drm_callbacks, disp, flags); 32703464ebd5Sriastradh 32717ec681f3Smrg free(device_name); 32727ec681f3Smrg 32733464ebd5Sriastradh if (!dri2_dpy->wl_server_drm) 327401e04c3fSmrg return EGL_FALSE; 32753464ebd5Sriastradh 3276af69d88dSmrg#ifdef HAVE_DRM_PLATFORM 3277af69d88dSmrg /* We have to share the wl_drm instance with gbm, so gbm can convert 3278af69d88dSmrg * wl_buffers to gbm bos. */ 3279af69d88dSmrg if (dri2_dpy->gbm_dri) 3280af69d88dSmrg dri2_dpy->gbm_dri->wl_drm = dri2_dpy->wl_server_drm; 3281af69d88dSmrg#endif 3282af69d88dSmrg 32833464ebd5Sriastradh return EGL_TRUE; 32843464ebd5Sriastradh} 32853464ebd5Sriastradh 32863464ebd5Sriastradhstatic EGLBoolean 32877ec681f3Smrgdri2_unbind_wayland_display_wl(_EGLDisplay *disp, struct wl_display *wl_dpy) 32883464ebd5Sriastradh{ 32893464ebd5Sriastradh struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 32903464ebd5Sriastradh 32913464ebd5Sriastradh if (!dri2_dpy->wl_server_drm) 329201e04c3fSmrg return EGL_FALSE; 32933464ebd5Sriastradh 32943464ebd5Sriastradh wayland_drm_uninit(dri2_dpy->wl_server_drm); 32953464ebd5Sriastradh dri2_dpy->wl_server_drm = NULL; 32963464ebd5Sriastradh 32973464ebd5Sriastradh return EGL_TRUE; 32983464ebd5Sriastradh} 3299af69d88dSmrg 3300af69d88dSmrgstatic EGLBoolean 33017ec681f3Smrgdri2_query_wayland_buffer_wl(_EGLDisplay *disp, struct wl_resource *buffer_resource, 3302af69d88dSmrg EGLint attribute, EGLint *value) 3303af69d88dSmrg{ 3304af69d88dSmrg struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 3305af69d88dSmrg struct wl_drm_buffer *buffer; 3306af69d88dSmrg const struct wl_drm_components_descriptor *format; 3307af69d88dSmrg 3308af69d88dSmrg buffer = wayland_drm_buffer_get(dri2_dpy->wl_server_drm, buffer_resource); 3309af69d88dSmrg if (!buffer) 3310af69d88dSmrg return EGL_FALSE; 3311af69d88dSmrg 3312af69d88dSmrg format = buffer->driver_format; 3313af69d88dSmrg switch (attribute) { 3314af69d88dSmrg case EGL_TEXTURE_FORMAT: 3315af69d88dSmrg *value = format->components; 3316af69d88dSmrg return EGL_TRUE; 3317af69d88dSmrg case EGL_WIDTH: 3318af69d88dSmrg *value = buffer->width; 3319af69d88dSmrg return EGL_TRUE; 3320af69d88dSmrg case EGL_HEIGHT: 3321af69d88dSmrg *value = buffer->height; 3322af69d88dSmrg return EGL_TRUE; 3323af69d88dSmrg } 3324af69d88dSmrg 3325af69d88dSmrg return EGL_FALSE; 3326af69d88dSmrg} 33273464ebd5Sriastradh#endif 33283464ebd5Sriastradh 33293464ebd5Sriastradhstatic void 333001e04c3fSmrgdri2_egl_ref_sync(struct dri2_egl_sync *sync) 33313464ebd5Sriastradh{ 333201e04c3fSmrg p_atomic_inc(&sync->refcount); 333301e04c3fSmrg} 33343464ebd5Sriastradh 333501e04c3fSmrgstatic void 333601e04c3fSmrgdri2_egl_unref_sync(struct dri2_egl_display *dri2_dpy, 333701e04c3fSmrg struct dri2_egl_sync *dri2_sync) 333801e04c3fSmrg{ 333901e04c3fSmrg if (p_atomic_dec_zero(&dri2_sync->refcount)) { 334001e04c3fSmrg switch (dri2_sync->base.Type) { 334101e04c3fSmrg case EGL_SYNC_REUSABLE_KHR: 334201e04c3fSmrg cnd_destroy(&dri2_sync->cond); 334301e04c3fSmrg break; 334401e04c3fSmrg case EGL_SYNC_NATIVE_FENCE_ANDROID: 334501e04c3fSmrg if (dri2_sync->base.SyncFd != EGL_NO_NATIVE_FENCE_FD_ANDROID) 334601e04c3fSmrg close(dri2_sync->base.SyncFd); 334701e04c3fSmrg break; 334801e04c3fSmrg default: 334901e04c3fSmrg break; 335001e04c3fSmrg } 335101e04c3fSmrg 335201e04c3fSmrg if (dri2_sync->fence) 335301e04c3fSmrg dri2_dpy->fence->destroy_fence(dri2_dpy->dri_screen, dri2_sync->fence); 335401e04c3fSmrg 335501e04c3fSmrg free(dri2_sync); 335601e04c3fSmrg } 335701e04c3fSmrg} 335801e04c3fSmrg 335901e04c3fSmrgstatic _EGLSync * 33607ec681f3Smrgdri2_create_sync(_EGLDisplay *disp, EGLenum type, const EGLAttrib *attrib_list) 336101e04c3fSmrg{ 336201e04c3fSmrg _EGLContext *ctx = _eglGetCurrentContext(); 33637e102996Smaya struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 336401e04c3fSmrg struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); 336501e04c3fSmrg struct dri2_egl_sync *dri2_sync; 336601e04c3fSmrg EGLint ret; 336701e04c3fSmrg pthread_condattr_t attr; 336801e04c3fSmrg 336901e04c3fSmrg dri2_sync = calloc(1, sizeof(struct dri2_egl_sync)); 337001e04c3fSmrg if (!dri2_sync) { 337101e04c3fSmrg _eglError(EGL_BAD_ALLOC, "eglCreateSyncKHR"); 337201e04c3fSmrg return NULL; 337301e04c3fSmrg } 337401e04c3fSmrg 33757e102996Smaya if (!_eglInitSync(&dri2_sync->base, disp, type, attrib_list)) { 337601e04c3fSmrg free(dri2_sync); 337701e04c3fSmrg return NULL; 337801e04c3fSmrg } 337901e04c3fSmrg 338001e04c3fSmrg switch (type) { 338101e04c3fSmrg case EGL_SYNC_FENCE_KHR: 338201e04c3fSmrg dri2_sync->fence = dri2_dpy->fence->create_fence(dri2_ctx->dri_context); 338301e04c3fSmrg if (!dri2_sync->fence) { 338401e04c3fSmrg /* Why did it fail? DRI doesn't return an error code, so we emit 338501e04c3fSmrg * a generic EGL error that doesn't communicate user error. 338601e04c3fSmrg */ 338701e04c3fSmrg _eglError(EGL_BAD_ALLOC, "eglCreateSyncKHR"); 338801e04c3fSmrg free(dri2_sync); 338901e04c3fSmrg return NULL; 339001e04c3fSmrg } 339101e04c3fSmrg break; 339201e04c3fSmrg 339301e04c3fSmrg case EGL_SYNC_CL_EVENT_KHR: 339401e04c3fSmrg dri2_sync->fence = dri2_dpy->fence->get_fence_from_cl_event( 339501e04c3fSmrg dri2_dpy->dri_screen, 339601e04c3fSmrg dri2_sync->base.CLEvent); 339701e04c3fSmrg /* this can only happen if the cl_event passed in is invalid. */ 339801e04c3fSmrg if (!dri2_sync->fence) { 339901e04c3fSmrg _eglError(EGL_BAD_ATTRIBUTE, "eglCreateSyncKHR"); 340001e04c3fSmrg free(dri2_sync); 340101e04c3fSmrg return NULL; 340201e04c3fSmrg } 340301e04c3fSmrg 340401e04c3fSmrg /* the initial status must be "signaled" if the cl_event is signaled */ 340501e04c3fSmrg if (dri2_dpy->fence->client_wait_sync(dri2_ctx->dri_context, 340601e04c3fSmrg dri2_sync->fence, 0, 0)) 340701e04c3fSmrg dri2_sync->base.SyncStatus = EGL_SIGNALED_KHR; 340801e04c3fSmrg break; 340901e04c3fSmrg 341001e04c3fSmrg case EGL_SYNC_REUSABLE_KHR: 341101e04c3fSmrg /* intialize attr */ 341201e04c3fSmrg ret = pthread_condattr_init(&attr); 341301e04c3fSmrg 341401e04c3fSmrg if (ret) { 341501e04c3fSmrg _eglError(EGL_BAD_ACCESS, "eglCreateSyncKHR"); 341601e04c3fSmrg free(dri2_sync); 341701e04c3fSmrg return NULL; 341801e04c3fSmrg } 341901e04c3fSmrg 342001e04c3fSmrg /* change clock attribute to CLOCK_MONOTONIC */ 342101e04c3fSmrg ret = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC); 342201e04c3fSmrg 342301e04c3fSmrg if (ret) { 342401e04c3fSmrg _eglError(EGL_BAD_ACCESS, "eglCreateSyncKHR"); 342501e04c3fSmrg free(dri2_sync); 342601e04c3fSmrg return NULL; 342701e04c3fSmrg } 342801e04c3fSmrg 342901e04c3fSmrg ret = pthread_cond_init(&dri2_sync->cond, &attr); 343001e04c3fSmrg 343101e04c3fSmrg if (ret) { 343201e04c3fSmrg _eglError(EGL_BAD_ACCESS, "eglCreateSyncKHR"); 343301e04c3fSmrg free(dri2_sync); 343401e04c3fSmrg return NULL; 343501e04c3fSmrg } 343601e04c3fSmrg 343701e04c3fSmrg /* initial status of reusable sync must be "unsignaled" */ 343801e04c3fSmrg dri2_sync->base.SyncStatus = EGL_UNSIGNALED_KHR; 343901e04c3fSmrg break; 344001e04c3fSmrg 344101e04c3fSmrg case EGL_SYNC_NATIVE_FENCE_ANDROID: 344201e04c3fSmrg if (dri2_dpy->fence->create_fence_fd) { 344301e04c3fSmrg dri2_sync->fence = dri2_dpy->fence->create_fence_fd( 344401e04c3fSmrg dri2_ctx->dri_context, 344501e04c3fSmrg dri2_sync->base.SyncFd); 344601e04c3fSmrg } 344701e04c3fSmrg if (!dri2_sync->fence) { 344801e04c3fSmrg _eglError(EGL_BAD_ATTRIBUTE, "eglCreateSyncKHR"); 344901e04c3fSmrg free(dri2_sync); 345001e04c3fSmrg return NULL; 345101e04c3fSmrg } 345201e04c3fSmrg break; 345301e04c3fSmrg } 345401e04c3fSmrg 345501e04c3fSmrg p_atomic_set(&dri2_sync->refcount, 1); 345601e04c3fSmrg return &dri2_sync->base; 34573464ebd5Sriastradh} 34583464ebd5Sriastradh 34593464ebd5Sriastradhstatic EGLBoolean 34607ec681f3Smrgdri2_destroy_sync(_EGLDisplay *disp, _EGLSync *sync) 346101e04c3fSmrg{ 34627e102996Smaya struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 346301e04c3fSmrg struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync); 346401e04c3fSmrg EGLint ret = EGL_TRUE; 346501e04c3fSmrg EGLint err; 346601e04c3fSmrg 346701e04c3fSmrg /* if type of sync is EGL_SYNC_REUSABLE_KHR and it is not signaled yet, 346801e04c3fSmrg * then unlock all threads possibly blocked by the reusable sync before 346901e04c3fSmrg * destroying it. 34703464ebd5Sriastradh */ 347101e04c3fSmrg if (dri2_sync->base.Type == EGL_SYNC_REUSABLE_KHR && 347201e04c3fSmrg dri2_sync->base.SyncStatus == EGL_UNSIGNALED_KHR) { 347301e04c3fSmrg dri2_sync->base.SyncStatus = EGL_SIGNALED_KHR; 347401e04c3fSmrg /* unblock all threads currently blocked by sync */ 347501e04c3fSmrg err = cnd_broadcast(&dri2_sync->cond); 347601e04c3fSmrg 347701e04c3fSmrg if (err) { 347801e04c3fSmrg _eglError(EGL_BAD_ACCESS, "eglDestroySyncKHR"); 347901e04c3fSmrg ret = EGL_FALSE; 34803464ebd5Sriastradh } 34813464ebd5Sriastradh } 34823464ebd5Sriastradh 348301e04c3fSmrg dri2_egl_unref_sync(dri2_dpy, dri2_sync); 348401e04c3fSmrg 348501e04c3fSmrg return ret; 348601e04c3fSmrg} 348701e04c3fSmrg 348801e04c3fSmrgstatic EGLint 34897ec681f3Smrgdri2_dup_native_fence_fd(_EGLDisplay *disp, _EGLSync *sync) 349001e04c3fSmrg{ 34917e102996Smaya struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 349201e04c3fSmrg struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync); 349301e04c3fSmrg 349401e04c3fSmrg assert(sync->Type == EGL_SYNC_NATIVE_FENCE_ANDROID); 349501e04c3fSmrg 349601e04c3fSmrg if (sync->SyncFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) { 349701e04c3fSmrg /* try to retrieve the actual native fence fd.. if rendering is 349801e04c3fSmrg * not flushed this will just return -1, aka NO_NATIVE_FENCE_FD: 349901e04c3fSmrg */ 350001e04c3fSmrg sync->SyncFd = dri2_dpy->fence->get_fence_fd(dri2_dpy->dri_screen, 350101e04c3fSmrg dri2_sync->fence); 35023464ebd5Sriastradh } 35033464ebd5Sriastradh 350401e04c3fSmrg if (sync->SyncFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) { 350501e04c3fSmrg /* if native fence fd still not created, return an error: */ 350601e04c3fSmrg _eglError(EGL_BAD_PARAMETER, "eglDupNativeFenceFDANDROID"); 350701e04c3fSmrg return EGL_NO_NATIVE_FENCE_FD_ANDROID; 350801e04c3fSmrg } 35093464ebd5Sriastradh 35107ec681f3Smrg assert(sync_valid_fd(sync->SyncFd)); 35117ec681f3Smrg 35127ec681f3Smrg return os_dupfd_cloexec(sync->SyncFd); 351301e04c3fSmrg} 35143464ebd5Sriastradh 351501e04c3fSmrgstatic void 35167ec681f3Smrgdri2_set_blob_cache_funcs(_EGLDisplay *disp, 351701e04c3fSmrg EGLSetBlobFuncANDROID set, 351801e04c3fSmrg EGLGetBlobFuncANDROID get) 351901e04c3fSmrg{ 35207e102996Smaya struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 352101e04c3fSmrg dri2_dpy->blob->set_cache_funcs(dri2_dpy->dri_screen, 35227e102996Smaya disp->BlobCacheSet, 35237e102996Smaya disp->BlobCacheGet); 35243464ebd5Sriastradh} 35253464ebd5Sriastradh 352601e04c3fSmrgstatic EGLint 35277ec681f3Smrgdri2_client_wait_sync(_EGLDisplay *disp, _EGLSync *sync, 352801e04c3fSmrg EGLint flags, EGLTime timeout) 3529cdc920a0Smrg{ 353001e04c3fSmrg _EGLContext *ctx = _eglGetCurrentContext(); 35317e102996Smaya struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 353201e04c3fSmrg struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); 353301e04c3fSmrg struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync); 353401e04c3fSmrg unsigned wait_flags = 0; 3535cdc920a0Smrg 353601e04c3fSmrg EGLint ret = EGL_CONDITION_SATISFIED_KHR; 35373464ebd5Sriastradh 353801e04c3fSmrg /* The EGL_KHR_fence_sync spec states: 353901e04c3fSmrg * 354001e04c3fSmrg * "If no context is current for the bound API, 354101e04c3fSmrg * the EGL_SYNC_FLUSH_COMMANDS_BIT_KHR bit is ignored. 354201e04c3fSmrg */ 354301e04c3fSmrg if (dri2_ctx && flags & EGL_SYNC_FLUSH_COMMANDS_BIT_KHR) 354401e04c3fSmrg wait_flags |= __DRI2_FENCE_FLAG_FLUSH_COMMANDS; 354501e04c3fSmrg 354601e04c3fSmrg /* the sync object should take a reference while waiting */ 354701e04c3fSmrg dri2_egl_ref_sync(dri2_sync); 354801e04c3fSmrg 354901e04c3fSmrg switch (sync->Type) { 355001e04c3fSmrg case EGL_SYNC_FENCE_KHR: 355101e04c3fSmrg case EGL_SYNC_NATIVE_FENCE_ANDROID: 355201e04c3fSmrg case EGL_SYNC_CL_EVENT_KHR: 355301e04c3fSmrg if (dri2_dpy->fence->client_wait_sync(dri2_ctx ? dri2_ctx->dri_context : NULL, 355401e04c3fSmrg dri2_sync->fence, wait_flags, 355501e04c3fSmrg timeout)) 355601e04c3fSmrg dri2_sync->base.SyncStatus = EGL_SIGNALED_KHR; 355701e04c3fSmrg else 355801e04c3fSmrg ret = EGL_TIMEOUT_EXPIRED_KHR; 355901e04c3fSmrg break; 3560cdc920a0Smrg 356101e04c3fSmrg case EGL_SYNC_REUSABLE_KHR: 356201e04c3fSmrg if (dri2_ctx && dri2_sync->base.SyncStatus == EGL_UNSIGNALED_KHR && 356301e04c3fSmrg (flags & EGL_SYNC_FLUSH_COMMANDS_BIT_KHR)) { 356401e04c3fSmrg /* flush context if EGL_SYNC_FLUSH_COMMANDS_BIT_KHR is set */ 356501e04c3fSmrg dri2_gl_flush(); 356601e04c3fSmrg } 356701e04c3fSmrg 356801e04c3fSmrg /* if timeout is EGL_FOREVER_KHR, it should wait without any timeout.*/ 356901e04c3fSmrg if (timeout == EGL_FOREVER_KHR) { 357001e04c3fSmrg mtx_lock(&dri2_sync->mutex); 357101e04c3fSmrg cnd_wait(&dri2_sync->cond, &dri2_sync->mutex); 357201e04c3fSmrg mtx_unlock(&dri2_sync->mutex); 357301e04c3fSmrg } else { 357401e04c3fSmrg /* if reusable sync has not been yet signaled */ 357501e04c3fSmrg if (dri2_sync->base.SyncStatus != EGL_SIGNALED_KHR) { 357601e04c3fSmrg /* timespecs for cnd_timedwait */ 357701e04c3fSmrg struct timespec current; 357801e04c3fSmrg struct timespec expire; 357901e04c3fSmrg 358001e04c3fSmrg /* We override the clock to monotonic when creating the condition 358101e04c3fSmrg * variable. */ 358201e04c3fSmrg clock_gettime(CLOCK_MONOTONIC, ¤t); 358301e04c3fSmrg 358401e04c3fSmrg /* calculating when to expire */ 358501e04c3fSmrg expire.tv_nsec = timeout % 1000000000L; 358601e04c3fSmrg expire.tv_sec = timeout / 1000000000L; 358701e04c3fSmrg 358801e04c3fSmrg expire.tv_nsec += current.tv_nsec; 358901e04c3fSmrg expire.tv_sec += current.tv_sec; 359001e04c3fSmrg 359101e04c3fSmrg /* expire.nsec now is a number between 0 and 1999999998 */ 359201e04c3fSmrg if (expire.tv_nsec > 999999999L) { 359301e04c3fSmrg expire.tv_sec++; 359401e04c3fSmrg expire.tv_nsec -= 1000000000L; 359501e04c3fSmrg } 359601e04c3fSmrg 359701e04c3fSmrg mtx_lock(&dri2_sync->mutex); 359801e04c3fSmrg ret = cnd_timedwait(&dri2_sync->cond, &dri2_sync->mutex, &expire); 359901e04c3fSmrg mtx_unlock(&dri2_sync->mutex); 360001e04c3fSmrg 360101e04c3fSmrg if (ret == thrd_busy) { 360201e04c3fSmrg if (dri2_sync->base.SyncStatus == EGL_UNSIGNALED_KHR) { 360301e04c3fSmrg ret = EGL_TIMEOUT_EXPIRED_KHR; 360401e04c3fSmrg } else { 360501e04c3fSmrg _eglError(EGL_BAD_ACCESS, "eglClientWaitSyncKHR"); 360601e04c3fSmrg ret = EGL_FALSE; 360701e04c3fSmrg } 360801e04c3fSmrg } 360901e04c3fSmrg } 361001e04c3fSmrg } 361101e04c3fSmrg break; 361201e04c3fSmrg } 361301e04c3fSmrg dri2_egl_unref_sync(dri2_dpy, dri2_sync); 361401e04c3fSmrg 361501e04c3fSmrg return ret; 361601e04c3fSmrg} 361701e04c3fSmrg 361801e04c3fSmrgstatic EGLBoolean 36197ec681f3Smrgdri2_signal_sync(_EGLDisplay *disp, _EGLSync *sync, EGLenum mode) 362001e04c3fSmrg{ 362101e04c3fSmrg struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync); 362201e04c3fSmrg EGLint ret; 362301e04c3fSmrg 362401e04c3fSmrg if (sync->Type != EGL_SYNC_REUSABLE_KHR) 362501e04c3fSmrg return _eglError(EGL_BAD_MATCH, "eglSignalSyncKHR"); 362601e04c3fSmrg 362701e04c3fSmrg if (mode != EGL_SIGNALED_KHR && mode != EGL_UNSIGNALED_KHR) 362801e04c3fSmrg return _eglError(EGL_BAD_ATTRIBUTE, "eglSignalSyncKHR"); 362901e04c3fSmrg 363001e04c3fSmrg dri2_sync->base.SyncStatus = mode; 363101e04c3fSmrg 363201e04c3fSmrg if (mode == EGL_SIGNALED_KHR) { 363301e04c3fSmrg ret = cnd_broadcast(&dri2_sync->cond); 363401e04c3fSmrg 363501e04c3fSmrg /* fail to broadcast */ 363601e04c3fSmrg if (ret) 363701e04c3fSmrg return _eglError(EGL_BAD_ACCESS, "eglSignalSyncKHR"); 3638af69d88dSmrg } 36393464ebd5Sriastradh 364001e04c3fSmrg return EGL_TRUE; 364101e04c3fSmrg} 364201e04c3fSmrg 364301e04c3fSmrgstatic EGLint 36447ec681f3Smrgdri2_server_wait_sync(_EGLDisplay *disp, _EGLSync *sync) 364501e04c3fSmrg{ 364601e04c3fSmrg _EGLContext *ctx = _eglGetCurrentContext(); 36477e102996Smaya struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 364801e04c3fSmrg struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); 364901e04c3fSmrg struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync); 365001e04c3fSmrg 365101e04c3fSmrg dri2_dpy->fence->server_wait_sync(dri2_ctx->dri_context, 365201e04c3fSmrg dri2_sync->fence, 0); 365301e04c3fSmrg return EGL_TRUE; 365401e04c3fSmrg} 365501e04c3fSmrg 365601e04c3fSmrgstatic int 36577e102996Smayadri2_interop_query_device_info(_EGLDisplay *disp, _EGLContext *ctx, 365801e04c3fSmrg struct mesa_glinterop_device_info *out) 365901e04c3fSmrg{ 36607e102996Smaya struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 366101e04c3fSmrg struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); 366201e04c3fSmrg 366301e04c3fSmrg if (!dri2_dpy->interop) 366401e04c3fSmrg return MESA_GLINTEROP_UNSUPPORTED; 366501e04c3fSmrg 366601e04c3fSmrg return dri2_dpy->interop->query_device_info(dri2_ctx->dri_context, out); 366701e04c3fSmrg} 366801e04c3fSmrg 366901e04c3fSmrgstatic int 36707e102996Smayadri2_interop_export_object(_EGLDisplay *disp, _EGLContext *ctx, 367101e04c3fSmrg struct mesa_glinterop_export_in *in, 367201e04c3fSmrg struct mesa_glinterop_export_out *out) 367301e04c3fSmrg{ 36747e102996Smaya struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 367501e04c3fSmrg struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); 367601e04c3fSmrg 367701e04c3fSmrg if (!dri2_dpy->interop) 367801e04c3fSmrg return MESA_GLINTEROP_UNSUPPORTED; 367901e04c3fSmrg 368001e04c3fSmrg return dri2_dpy->interop->export_object(dri2_ctx->dri_context, in, out); 368101e04c3fSmrg} 368201e04c3fSmrg 36837ec681f3Smrgconst _EGLDriver _eglDriver = { 36847ec681f3Smrg .Initialize = dri2_initialize, 36857ec681f3Smrg .Terminate = dri2_terminate, 36867ec681f3Smrg .CreateContext = dri2_create_context, 36877ec681f3Smrg .DestroyContext = dri2_destroy_context, 36887ec681f3Smrg .MakeCurrent = dri2_make_current, 36897ec681f3Smrg .CreateWindowSurface = dri2_create_window_surface, 36907ec681f3Smrg .CreatePixmapSurface = dri2_create_pixmap_surface, 36917ec681f3Smrg .CreatePbufferSurface = dri2_create_pbuffer_surface, 36927ec681f3Smrg .DestroySurface = dri2_destroy_surface, 36937ec681f3Smrg .GetProcAddress = dri2_get_proc_address, 36947ec681f3Smrg .WaitClient = dri2_wait_client, 36957ec681f3Smrg .WaitNative = dri2_wait_native, 36967ec681f3Smrg .BindTexImage = dri2_bind_tex_image, 36977ec681f3Smrg .ReleaseTexImage = dri2_release_tex_image, 36987ec681f3Smrg .SwapInterval = dri2_swap_interval, 36997ec681f3Smrg .SwapBuffers = dri2_swap_buffers, 37007ec681f3Smrg .SwapBuffersWithDamageEXT = dri2_swap_buffers_with_damage, 37017ec681f3Smrg .SwapBuffersRegionNOK = dri2_swap_buffers_region, 37027ec681f3Smrg .SetDamageRegion = dri2_set_damage_region, 37037ec681f3Smrg .PostSubBufferNV = dri2_post_sub_buffer, 37047ec681f3Smrg .CopyBuffers = dri2_copy_buffers, 37057ec681f3Smrg .QueryBufferAge = dri2_query_buffer_age, 37067ec681f3Smrg .CreateImageKHR = dri2_create_image, 37077ec681f3Smrg .DestroyImageKHR = dri2_destroy_image_khr, 37087ec681f3Smrg .CreateWaylandBufferFromImageWL = dri2_create_wayland_buffer_from_image, 37097ec681f3Smrg .QuerySurface = dri2_query_surface, 37107ec681f3Smrg .QueryDriverName = dri2_query_driver_name, 37117ec681f3Smrg .QueryDriverConfig = dri2_query_driver_config, 371201e04c3fSmrg#ifdef HAVE_LIBDRM 37137ec681f3Smrg .CreateDRMImageMESA = dri2_create_drm_image_mesa, 37147ec681f3Smrg .ExportDRMImageMESA = dri2_export_drm_image_mesa, 37157ec681f3Smrg .ExportDMABUFImageQueryMESA = dri2_export_dma_buf_image_query_mesa, 37167ec681f3Smrg .ExportDMABUFImageMESA = dri2_export_dma_buf_image_mesa, 37177ec681f3Smrg .QueryDmaBufFormatsEXT = dri2_query_dma_buf_formats, 37187ec681f3Smrg .QueryDmaBufModifiersEXT = dri2_query_dma_buf_modifiers, 3719af69d88dSmrg#endif 37203464ebd5Sriastradh#ifdef HAVE_WAYLAND_PLATFORM 37217ec681f3Smrg .BindWaylandDisplayWL = dri2_bind_wayland_display_wl, 37227ec681f3Smrg .UnbindWaylandDisplayWL = dri2_unbind_wayland_display_wl, 37237ec681f3Smrg .QueryWaylandBufferWL = dri2_query_wayland_buffer_wl, 37243464ebd5Sriastradh#endif 37257ec681f3Smrg .GetSyncValuesCHROMIUM = dri2_get_sync_values_chromium, 37267ec681f3Smrg .CreateSyncKHR = dri2_create_sync, 37277ec681f3Smrg .ClientWaitSyncKHR = dri2_client_wait_sync, 37287ec681f3Smrg .SignalSyncKHR = dri2_signal_sync, 37297ec681f3Smrg .WaitSyncKHR = dri2_server_wait_sync, 37307ec681f3Smrg .DestroySyncKHR = dri2_destroy_sync, 37317ec681f3Smrg .GLInteropQueryDeviceInfo = dri2_interop_query_device_info, 37327ec681f3Smrg .GLInteropExportObject = dri2_interop_export_object, 37337ec681f3Smrg .DupNativeFenceFDANDROID = dri2_dup_native_fence_fd, 37347ec681f3Smrg .SetBlobCacheFuncsANDROID = dri2_set_blob_cache_funcs, 37357ec681f3Smrg}; 3736