egl_dri2.c revision 00978098794f723230a33cab1c1152686f1c4fa5
1b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek/*
277349cb20bfd7069d081f84c91975bfa8ef60a32Ted Kremenek * Copyright © 2010 Intel Corporation
377349cb20bfd7069d081f84c91975bfa8ef60a32Ted Kremenek *
477349cb20bfd7069d081f84c91975bfa8ef60a32Ted Kremenek * Permission is hereby granted, free of charge, to any person obtaining a
577349cb20bfd7069d081f84c91975bfa8ef60a32Ted Kremenek * copy of this software and associated documentation files (the "Software"),
677349cb20bfd7069d081f84c91975bfa8ef60a32Ted Kremenek * to deal in the Software without restriction, including without limitation
777349cb20bfd7069d081f84c91975bfa8ef60a32Ted Kremenek * the rights to use, copy, modify, merge, publish, distribute, sublicense,
877349cb20bfd7069d081f84c91975bfa8ef60a32Ted Kremenek * and/or sell copies of the Software, and to permit persons to whom the
977349cb20bfd7069d081f84c91975bfa8ef60a32Ted Kremenek * Software is furnished to do so, subject to the following conditions:
10b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek *
11b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek * The above copyright notice and this permission notice (including the next
12b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek * paragraph) shall be included in all copies or substantial portions of the
1377349cb20bfd7069d081f84c91975bfa8ef60a32Ted Kremenek * Software.
1477349cb20bfd7069d081f84c91975bfa8ef60a32Ted Kremenek *
1577349cb20bfd7069d081f84c91975bfa8ef60a32Ted Kremenek * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16d065d6080f0620bb80b933f3f5d52d37bb2ea770Ted Kremenek * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17d065d6080f0620bb80b933f3f5d52d37bb2ea770Ted Kremenek * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18d065d6080f0620bb80b933f3f5d52d37bb2ea770Ted Kremenek * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
1977349cb20bfd7069d081f84c91975bfa8ef60a32Ted Kremenek * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20aed9b6ac2ed0013133e4d4aebf2fad2ccd27f3e6Ted Kremenek * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2199c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
2277349cb20bfd7069d081f84c91975bfa8ef60a32Ted Kremenek * DEALINGS IN THE SOFTWARE.
2377349cb20bfd7069d081f84c91975bfa8ef60a32Ted Kremenek *
24b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek * Authors:
2577349cb20bfd7069d081f84c91975bfa8ef60a32Ted Kremenek *    Kristian Høgsberg <krh@bitplanet.net>
2699c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek */
2799c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
28b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek#include <stdlib.h>
29b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek#include <string.h>
30b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek#include <stdio.h>
31e5f4dcb6bd73a10df6eb6c3cfe057c88cb2362ccTed Kremenek#include <limits.h>
32b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek#include <dlfcn.h>
33aa1c4e5a6b87b62d991c55a0d4522bcd778068d7Ted Kremenek#include <fcntl.h>
34b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek#include <errno.h>
35b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek#include <unistd.h>
36f116bd654bcdb5d7c22656f224deeb7a67f7d0cdTed Kremenek#include <xf86drm.h>
37aa1c4e5a6b87b62d991c55a0d4522bcd778068d7Ted Kremenek#include <GL/gl.h>
38aa1c4e5a6b87b62d991c55a0d4522bcd778068d7Ted Kremenek#include <GL/internal/dri_interface.h>
39aa1c4e5a6b87b62d991c55a0d4522bcd778068d7Ted Kremenek#include <sys/types.h>
40330dddd19406f9cc227e59e0bb0a36ecdc52915eTed Kremenek#include <sys/stat.h>
4199c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
4277349cb20bfd7069d081f84c91975bfa8ef60a32Ted Kremenek#include "egl_dri2.h"
43b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek
44b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenekconst __DRIuseInvalidateExtension use_invalidate = {
45b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek   { __DRI_USE_INVALIDATE, 1 }
46b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek};
47b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek
48b387a3f23e423d62c053be86294b703da1d1a222Ted KremenekEGLint dri2_to_egl_attribute_map[] = {
49b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek   0,
50b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek   EGL_BUFFER_SIZE,		/* __DRI_ATTRIB_BUFFER_SIZE */
51b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek   EGL_LEVEL,			/* __DRI_ATTRIB_LEVEL */
52b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek   EGL_RED_SIZE,		/* __DRI_ATTRIB_RED_SIZE */
53b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek   EGL_GREEN_SIZE,		/* __DRI_ATTRIB_GREEN_SIZE */
54b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek   EGL_BLUE_SIZE,		/* __DRI_ATTRIB_BLUE_SIZE */
55b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek   EGL_LUMINANCE_SIZE,		/* __DRI_ATTRIB_LUMINANCE_SIZE */
56b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek   EGL_ALPHA_SIZE,		/* __DRI_ATTRIB_ALPHA_SIZE */
57b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek   0,				/* __DRI_ATTRIB_ALPHA_MASK_SIZE */
58aa1c4e5a6b87b62d991c55a0d4522bcd778068d7Ted Kremenek   EGL_DEPTH_SIZE,		/* __DRI_ATTRIB_DEPTH_SIZE */
59240f1f00dda1d481276ea872fe8f8851581a7e6bTed Kremenek   EGL_STENCIL_SIZE,		/* __DRI_ATTRIB_STENCIL_SIZE */
60b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek   0,				/* __DRI_ATTRIB_ACCUM_RED_SIZE */
61b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek   0,				/* __DRI_ATTRIB_ACCUM_GREEN_SIZE */
62aa1c4e5a6b87b62d991c55a0d4522bcd778068d7Ted Kremenek   0,				/* __DRI_ATTRIB_ACCUM_BLUE_SIZE */
63b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek   0,				/* __DRI_ATTRIB_ACCUM_ALPHA_SIZE */
64b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek   EGL_SAMPLE_BUFFERS,		/* __DRI_ATTRIB_SAMPLE_BUFFERS */
65b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek   EGL_SAMPLES,			/* __DRI_ATTRIB_SAMPLES */
66b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek   0,				/* __DRI_ATTRIB_RENDER_TYPE, */
67b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek   0,				/* __DRI_ATTRIB_CONFIG_CAVEAT */
68b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek   0,				/* __DRI_ATTRIB_CONFORMANT */
69b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek   0,				/* __DRI_ATTRIB_DOUBLE_BUFFER */
70b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek   0,				/* __DRI_ATTRIB_STEREO */
710d093d3005dd583675a45a85bd688063572cc8afTed Kremenek   0,				/* __DRI_ATTRIB_AUX_BUFFERS */
720d093d3005dd583675a45a85bd688063572cc8afTed Kremenek   0,				/* __DRI_ATTRIB_TRANSPARENT_TYPE */
730d093d3005dd583675a45a85bd688063572cc8afTed Kremenek   0,				/* __DRI_ATTRIB_TRANSPARENT_INDEX_VALUE */
740d093d3005dd583675a45a85bd688063572cc8afTed Kremenek   0,				/* __DRI_ATTRIB_TRANSPARENT_RED_VALUE */
75b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek   0,				/* __DRI_ATTRIB_TRANSPARENT_GREEN_VALUE */
76b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek   0,				/* __DRI_ATTRIB_TRANSPARENT_BLUE_VALUE */
7799c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek   0,				/* __DRI_ATTRIB_TRANSPARENT_ALPHA_VALUE */
7899c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek   0,				/* __DRI_ATTRIB_FLOAT_MODE */
7999c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek   0,				/* __DRI_ATTRIB_RED_MASK */
8099c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek   0,				/* __DRI_ATTRIB_GREEN_MASK */
8199c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek   0,				/* __DRI_ATTRIB_BLUE_MASK */
8299c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek   0,				/* __DRI_ATTRIB_ALPHA_MASK */
83affb2159712b2373a18a89ed205c1a309d3aec12Ted Kremenek   EGL_MAX_PBUFFER_WIDTH,	/* __DRI_ATTRIB_MAX_PBUFFER_WIDTH */
844a4e524afef40d6f3ddb25d0e407c814e4ca56a8Ted Kremenek   EGL_MAX_PBUFFER_HEIGHT,	/* __DRI_ATTRIB_MAX_PBUFFER_HEIGHT */
854a4e524afef40d6f3ddb25d0e407c814e4ca56a8Ted Kremenek   EGL_MAX_PBUFFER_PIXELS,	/* __DRI_ATTRIB_MAX_PBUFFER_PIXELS */
86affb2159712b2373a18a89ed205c1a309d3aec12Ted Kremenek   0,				/* __DRI_ATTRIB_OPTIMAL_PBUFFER_WIDTH */
875e03fcb5420c33207433dd6f800588e256dd9bdbTed Kremenek   0,				/* __DRI_ATTRIB_OPTIMAL_PBUFFER_HEIGHT */
8823a4f917cd8d1090be7c96c4eda8643086f64d36Ted Kremenek   0,				/* __DRI_ATTRIB_VISUAL_SELECT_GROUP */
891e80aa49ec689d1937e54fb353d6626e0a58f0dbTed Kremenek   0,				/* __DRI_ATTRIB_SWAP_METHOD */
90affb2159712b2373a18a89ed205c1a309d3aec12Ted Kremenek   EGL_MAX_SWAP_INTERVAL,	/* __DRI_ATTRIB_MAX_SWAP_INTERVAL */
91affb2159712b2373a18a89ed205c1a309d3aec12Ted Kremenek   EGL_MIN_SWAP_INTERVAL,	/* __DRI_ATTRIB_MIN_SWAP_INTERVAL */
9202737ed29d7fff2206f7c7ee958cdf0665e35542Ted Kremenek   0,				/* __DRI_ATTRIB_BIND_TO_TEXTURE_RGB */
9302737ed29d7fff2206f7c7ee958cdf0665e35542Ted Kremenek   0,				/* __DRI_ATTRIB_BIND_TO_TEXTURE_RGBA */
948cc13ea74fea1c04042a2f4087665bc5182e8408Ted Kremenek   0,				/* __DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE */
9502737ed29d7fff2206f7c7ee958cdf0665e35542Ted Kremenek   0,				/* __DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS */
9602737ed29d7fff2206f7c7ee958cdf0665e35542Ted Kremenek   EGL_Y_INVERTED_NOK,		/* __DRI_ATTRIB_YINVERTED */
9702737ed29d7fff2206f7c7ee958cdf0665e35542Ted Kremenek   0,				/* __DRI_ATTRIB_FRAMEBUFFER_SRGB_CAPABLE */
98b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek};
994a4e524afef40d6f3ddb25d0e407c814e4ca56a8Ted Kremenek
1004a4e524afef40d6f3ddb25d0e407c814e4ca56a8Ted Kremenekstatic EGLBoolean
1014a4e524afef40d6f3ddb25d0e407c814e4ca56a8Ted Kremenekdri2_match_config(const _EGLConfig *conf, const _EGLConfig *criteria)
102b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek{
1034a4e524afef40d6f3ddb25d0e407c814e4ca56a8Ted Kremenek   if (_eglCompareConfigs(conf, criteria, NULL, EGL_FALSE) != 0)
1044a4e524afef40d6f3ddb25d0e407c814e4ca56a8Ted Kremenek      return EGL_FALSE;
1054a4e524afef40d6f3ddb25d0e407c814e4ca56a8Ted Kremenek
1069dca062461a6244cf0f733346657fa3eee853f9bTed Kremenek   if (!_eglMatchConfig(conf, criteria))
107affb2159712b2373a18a89ed205c1a309d3aec12Ted Kremenek      return EGL_FALSE;
108affb2159712b2373a18a89ed205c1a309d3aec12Ted Kremenek
109affb2159712b2373a18a89ed205c1a309d3aec12Ted Kremenek   return EGL_TRUE;
110affb2159712b2373a18a89ed205c1a309d3aec12Ted Kremenek}
111b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek
11207d83aa220567bef263ef76cfc9b0159320bb640Ted Kremenekstruct dri2_egl_config *
113b5339121f63f2754d4f26e8f3a092caf9f7d9290Ted Kremenekdri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id,
11407d83aa220567bef263ef76cfc9b0159320bb640Ted Kremenek		int depth, EGLint surface_type, const EGLint *attr_list,
11507d83aa220567bef263ef76cfc9b0159320bb640Ted Kremenek		const unsigned int *rgba_masks)
11607d83aa220567bef263ef76cfc9b0159320bb640Ted Kremenek{
117b5339121f63f2754d4f26e8f3a092caf9f7d9290Ted Kremenek   struct dri2_egl_config *conf;
11807d83aa220567bef263ef76cfc9b0159320bb640Ted Kremenek   struct dri2_egl_display *dri2_dpy;
11907d83aa220567bef263ef76cfc9b0159320bb640Ted Kremenek   _EGLConfig base;
1204a4e524afef40d6f3ddb25d0e407c814e4ca56a8Ted Kremenek   unsigned int attrib, value, double_buffer;
1214a4e524afef40d6f3ddb25d0e407c814e4ca56a8Ted Kremenek   EGLint key, bind_to_texture_rgb, bind_to_texture_rgba;
12207d83aa220567bef263ef76cfc9b0159320bb640Ted Kremenek   unsigned int dri_masks[4] = { 0, 0, 0, 0 };
1234d839b4949efe9e2b16eeab679c25b28e31ea742Ted Kremenek   _EGLConfig *matching_config;
1244d839b4949efe9e2b16eeab679c25b28e31ea742Ted Kremenek   EGLint num_configs = 0;
1254d839b4949efe9e2b16eeab679c25b28e31ea742Ted Kremenek   EGLint config_id;
1264d839b4949efe9e2b16eeab679c25b28e31ea742Ted Kremenek   int i;
1274d839b4949efe9e2b16eeab679c25b28e31ea742Ted Kremenek
1284d839b4949efe9e2b16eeab679c25b28e31ea742Ted Kremenek   dri2_dpy = disp->DriverData;
1294d839b4949efe9e2b16eeab679c25b28e31ea742Ted Kremenek   _eglInitConfig(&base, disp, id);
1304d839b4949efe9e2b16eeab679c25b28e31ea742Ted Kremenek
1314d839b4949efe9e2b16eeab679c25b28e31ea742Ted Kremenek   i = 0;
132b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek   double_buffer = 0;
1338cc13ea74fea1c04042a2f4087665bc5182e8408Ted Kremenek   bind_to_texture_rgb = 0;
1348cc13ea74fea1c04042a2f4087665bc5182e8408Ted Kremenek   bind_to_texture_rgba = 0;
1358cc13ea74fea1c04042a2f4087665bc5182e8408Ted Kremenek
1368cc13ea74fea1c04042a2f4087665bc5182e8408Ted Kremenek   while (dri2_dpy->core->indexConfigAttrib(dri_config, i++, &attrib, &value)) {
1375e03fcb5420c33207433dd6f800588e256dd9bdbTed Kremenek      switch (attrib) {
1385e03fcb5420c33207433dd6f800588e256dd9bdbTed Kremenek      case __DRI_ATTRIB_RENDER_TYPE:
1395e03fcb5420c33207433dd6f800588e256dd9bdbTed Kremenek	 if (value & __DRI_ATTRIB_RGBA_BIT)
1405e03fcb5420c33207433dd6f800588e256dd9bdbTed Kremenek	    value = EGL_RGB_BUFFER;
14123a4f917cd8d1090be7c96c4eda8643086f64d36Ted Kremenek	 else if (value & __DRI_ATTRIB_LUMINANCE_BIT)
14223a4f917cd8d1090be7c96c4eda8643086f64d36Ted Kremenek	    value = EGL_LUMINANCE_BUFFER;
14323a4f917cd8d1090be7c96c4eda8643086f64d36Ted Kremenek	 else
14423a4f917cd8d1090be7c96c4eda8643086f64d36Ted Kremenek	    /* not valid */;
1452ded35a576e3899553ea0ccfcbf5cbdb3d8cf664Ted Kremenek	 _eglSetConfigKey(&base, EGL_COLOR_BUFFER_TYPE, value);
1462ded35a576e3899553ea0ccfcbf5cbdb3d8cf664Ted Kremenek	 break;
1472ded35a576e3899553ea0ccfcbf5cbdb3d8cf664Ted Kremenek
1482ded35a576e3899553ea0ccfcbf5cbdb3d8cf664Ted Kremenek      case __DRI_ATTRIB_CONFIG_CAVEAT:
14923a4f917cd8d1090be7c96c4eda8643086f64d36Ted Kremenek         if (value & __DRI_ATTRIB_NON_CONFORMANT_CONFIG)
15023a4f917cd8d1090be7c96c4eda8643086f64d36Ted Kremenek            value = EGL_NON_CONFORMANT_CONFIG;
15123a4f917cd8d1090be7c96c4eda8643086f64d36Ted Kremenek         else if (value & __DRI_ATTRIB_SLOW_BIT)
15223a4f917cd8d1090be7c96c4eda8643086f64d36Ted Kremenek            value = EGL_SLOW_CONFIG;
15323a4f917cd8d1090be7c96c4eda8643086f64d36Ted Kremenek	 else
154b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek	    value = EGL_NONE;
155b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek	 _eglSetConfigKey(&base, EGL_CONFIG_CAVEAT, value);
1567cb15939e08ea31f0fadcd24c974dbc9e4b61c01Ted Kremenek         break;
1570d093d3005dd583675a45a85bd688063572cc8afTed Kremenek
1580d093d3005dd583675a45a85bd688063572cc8afTed Kremenek      case __DRI_ATTRIB_BIND_TO_TEXTURE_RGB:
1590d093d3005dd583675a45a85bd688063572cc8afTed Kremenek	 bind_to_texture_rgb = value;
1600d093d3005dd583675a45a85bd688063572cc8afTed Kremenek	 break;
1610d093d3005dd583675a45a85bd688063572cc8afTed Kremenek
1620d093d3005dd583675a45a85bd688063572cc8afTed Kremenek      case __DRI_ATTRIB_BIND_TO_TEXTURE_RGBA:
163b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek	 bind_to_texture_rgba = value;
164b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek	 break;
165b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek
166b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek      case __DRI_ATTRIB_DOUBLE_BUFFER:
167b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek	 double_buffer = value;
168b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek	 break;
169b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek
170b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek      case __DRI_ATTRIB_RED_MASK:
171b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek         dri_masks[0] = value;
172b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek         break;
173b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek
174b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek      case __DRI_ATTRIB_GREEN_MASK:
175b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek         dri_masks[1] = value;
176b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek         break;
177b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek
178b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek      case __DRI_ATTRIB_BLUE_MASK:
179e01c98767dfd7153c3c84637c36659e3bbe16ff7Ted Kremenek         dri_masks[2] = value;
180e01c98767dfd7153c3c84637c36659e3bbe16ff7Ted Kremenek         break;
181ffe0f43806d4823271c2406c1fccc2373115c36aTed Kremenek
182e01c98767dfd7153c3c84637c36659e3bbe16ff7Ted Kremenek      case __DRI_ATTRIB_ALPHA_MASK:
183493d7a26d5ea319770ba904b43f2740d43b820cbTed Kremenek         dri_masks[3] = value;
184493d7a26d5ea319770ba904b43f2740d43b820cbTed Kremenek         break;
185b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek
186b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek      default:
187aed9b6ac2ed0013133e4d4aebf2fad2ccd27f3e6Ted Kremenek	 key = dri2_to_egl_attribute_map[attrib];
188b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek	 if (key != 0)
18902737ed29d7fff2206f7c7ee958cdf0665e35542Ted Kremenek	    _eglSetConfigKey(&base, key, value);
19002737ed29d7fff2206f7c7ee958cdf0665e35542Ted Kremenek	 break;
19102737ed29d7fff2206f7c7ee958cdf0665e35542Ted Kremenek      }
19202737ed29d7fff2206f7c7ee958cdf0665e35542Ted Kremenek   }
1934a4e524afef40d6f3ddb25d0e407c814e4ca56a8Ted Kremenek
1944a4e524afef40d6f3ddb25d0e407c814e4ca56a8Ted Kremenek   if (attr_list)
195b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek      for (i = 0; attr_list[i] != EGL_NONE; i += 2)
196b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek         _eglSetConfigKey(&base, attr_list[i], attr_list[i+1]);
1974a4e524afef40d6f3ddb25d0e407c814e4ca56a8Ted Kremenek
1984a4e524afef40d6f3ddb25d0e407c814e4ca56a8Ted Kremenek   if (depth > 0 && depth != base.BufferSize)
1999dca062461a6244cf0f733346657fa3eee853f9bTed Kremenek      return NULL;
2009dca062461a6244cf0f733346657fa3eee853f9bTed Kremenek
201b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek   if (rgba_masks && memcmp(rgba_masks, dri_masks, sizeof(dri_masks)))
202b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek      return NULL;
203b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek
204b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek   base.NativeRenderable = EGL_TRUE;
205b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek
206b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek   base.SurfaceType = surface_type;
207b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek   if (surface_type & (EGL_PBUFFER_BIT |
208b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek       (disp->Extensions.NOK_texture_from_pixmap ? EGL_PIXMAP_BIT : 0))) {
2094a4e524afef40d6f3ddb25d0e407c814e4ca56a8Ted Kremenek      base.BindToTextureRGB = bind_to_texture_rgb;
2104a4e524afef40d6f3ddb25d0e407c814e4ca56a8Ted Kremenek      if (base.AlphaSize > 0)
211b5339121f63f2754d4f26e8f3a092caf9f7d9290Ted Kremenek         base.BindToTextureRGBA = bind_to_texture_rgba;
212b5339121f63f2754d4f26e8f3a092caf9f7d9290Ted Kremenek   }
2134d839b4949efe9e2b16eeab679c25b28e31ea742Ted Kremenek
2144d839b4949efe9e2b16eeab679c25b28e31ea742Ted Kremenek   base.RenderableType = disp->ClientAPIs;
2154d839b4949efe9e2b16eeab679c25b28e31ea742Ted Kremenek   base.Conformant = disp->ClientAPIs;
2164d839b4949efe9e2b16eeab679c25b28e31ea742Ted Kremenek
2174d839b4949efe9e2b16eeab679c25b28e31ea742Ted Kremenek   if (!_eglValidateConfig(&base, EGL_FALSE)) {
2184d839b4949efe9e2b16eeab679c25b28e31ea742Ted Kremenek      _eglLog(_EGL_DEBUG, "DRI2: failed to validate config %d", id);
219d763eb91aab5bdecd11825fadb35d6d8cc905f63Ted Kremenek      return NULL;
220d763eb91aab5bdecd11825fadb35d6d8cc905f63Ted Kremenek   }
221affb2159712b2373a18a89ed205c1a309d3aec12Ted Kremenek
222affb2159712b2373a18a89ed205c1a309d3aec12Ted Kremenek   config_id = base.ConfigID;
223affb2159712b2373a18a89ed205c1a309d3aec12Ted Kremenek   base.ConfigID    = EGL_DONT_CARE;
2248cc13ea74fea1c04042a2f4087665bc5182e8408Ted Kremenek   base.SurfaceType = EGL_DONT_CARE;
2258cc13ea74fea1c04042a2f4087665bc5182e8408Ted Kremenek   num_configs = _eglFilterArray(disp->Configs, (void **) &matching_config, 1,
2268cc13ea74fea1c04042a2f4087665bc5182e8408Ted Kremenek                                 (_EGLArrayForEach) dri2_match_config, &base);
2278cc13ea74fea1c04042a2f4087665bc5182e8408Ted Kremenek
2288cc13ea74fea1c04042a2f4087665bc5182e8408Ted Kremenek   if (num_configs == 1) {
2295e03fcb5420c33207433dd6f800588e256dd9bdbTed Kremenek      conf = (struct dri2_egl_config *) matching_config;
2305e03fcb5420c33207433dd6f800588e256dd9bdbTed Kremenek
2315e03fcb5420c33207433dd6f800588e256dd9bdbTed Kremenek      if (double_buffer && !conf->dri_double_config)
2325e03fcb5420c33207433dd6f800588e256dd9bdbTed Kremenek         conf->dri_double_config = dri_config;
2332ded35a576e3899553ea0ccfcbf5cbdb3d8cf664Ted Kremenek      else if (!double_buffer && !conf->dri_single_config)
2341e80aa49ec689d1937e54fb353d6626e0a58f0dbTed Kremenek         conf->dri_single_config = dri_config;
235dbfe41acda3078f8fe566318c0097f7ae683c6bbTed Kremenek      else
236dbfe41acda3078f8fe566318c0097f7ae683c6bbTed Kremenek         /* a similar config type is already added (unlikely) => discard */
237dbfe41acda3078f8fe566318c0097f7ae683c6bbTed Kremenek         return NULL;
238dbfe41acda3078f8fe566318c0097f7ae683c6bbTed Kremenek   }
239dbfe41acda3078f8fe566318c0097f7ae683c6bbTed Kremenek   else if (num_configs == 0) {
240dbfe41acda3078f8fe566318c0097f7ae683c6bbTed Kremenek      conf = malloc(sizeof *conf);
2412ded35a576e3899553ea0ccfcbf5cbdb3d8cf664Ted Kremenek      if (conf == NULL)
2422ded35a576e3899553ea0ccfcbf5cbdb3d8cf664Ted Kremenek         return NULL;
24302737ed29d7fff2206f7c7ee958cdf0665e35542Ted Kremenek
24402737ed29d7fff2206f7c7ee958cdf0665e35542Ted Kremenek      memcpy(&conf->base, &base, sizeof base);
24502737ed29d7fff2206f7c7ee958cdf0665e35542Ted Kremenek      if (double_buffer) {
24602737ed29d7fff2206f7c7ee958cdf0665e35542Ted Kremenek         conf->dri_double_config = dri_config;
2471b9df4c307b650526344ba0a28534268f6920745Ted Kremenek         conf->dri_single_config = NULL;
2481b9df4c307b650526344ba0a28534268f6920745Ted Kremenek      } else {
2491b9df4c307b650526344ba0a28534268f6920745Ted Kremenek         conf->dri_single_config = dri_config;
2501b9df4c307b650526344ba0a28534268f6920745Ted Kremenek         conf->dri_double_config = NULL;
251d87a321a3c3902f7acfc6539b8946a00da6e45ccTed Kremenek      }
252d87a321a3c3902f7acfc6539b8946a00da6e45ccTed Kremenek      conf->base.SurfaceType = 0;
253d87a321a3c3902f7acfc6539b8946a00da6e45ccTed Kremenek      conf->base.ConfigID = config_id;
254d87a321a3c3902f7acfc6539b8946a00da6e45ccTed Kremenek
2554a4e524afef40d6f3ddb25d0e407c814e4ca56a8Ted Kremenek      _eglLinkConfig(&conf->base);
2564a4e524afef40d6f3ddb25d0e407c814e4ca56a8Ted Kremenek   }
2574a4e524afef40d6f3ddb25d0e407c814e4ca56a8Ted Kremenek   else {
258d87a321a3c3902f7acfc6539b8946a00da6e45ccTed Kremenek      assert(0);
259d87a321a3c3902f7acfc6539b8946a00da6e45ccTed Kremenek      return NULL;
2604d839b4949efe9e2b16eeab679c25b28e31ea742Ted Kremenek   }
2614d839b4949efe9e2b16eeab679c25b28e31ea742Ted Kremenek
2624d839b4949efe9e2b16eeab679c25b28e31ea742Ted Kremenek   if (double_buffer) {
2634d839b4949efe9e2b16eeab679c25b28e31ea742Ted Kremenek      surface_type &= ~EGL_PIXMAP_BIT;
2644d839b4949efe9e2b16eeab679c25b28e31ea742Ted Kremenek
2654d839b4949efe9e2b16eeab679c25b28e31ea742Ted Kremenek      if (dri2_dpy->swap_available) {
2664d839b4949efe9e2b16eeab679c25b28e31ea742Ted Kremenek         conf->base.MinSwapInterval = 0;
2674d839b4949efe9e2b16eeab679c25b28e31ea742Ted Kremenek         conf->base.MaxSwapInterval = 1000; /* XXX arbitrary value */
2684d839b4949efe9e2b16eeab679c25b28e31ea742Ted Kremenek      }
2694d839b4949efe9e2b16eeab679c25b28e31ea742Ted Kremenek   }
2704d839b4949efe9e2b16eeab679c25b28e31ea742Ted Kremenek
2714d839b4949efe9e2b16eeab679c25b28e31ea742Ted Kremenek   conf->base.SurfaceType |= surface_type;
2724d839b4949efe9e2b16eeab679c25b28e31ea742Ted Kremenek
2734d839b4949efe9e2b16eeab679c25b28e31ea742Ted Kremenek   return conf;
2744d839b4949efe9e2b16eeab679c25b28e31ea742Ted Kremenek}
2754d839b4949efe9e2b16eeab679c25b28e31ea742Ted Kremenek
276b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek__DRIimage *
2778cc13ea74fea1c04042a2f4087665bc5182e8408Ted Kremenekdri2_lookup_egl_image(__DRIscreen *screen, void *image, void *data)
2788cc13ea74fea1c04042a2f4087665bc5182e8408Ted Kremenek{
2798cc13ea74fea1c04042a2f4087665bc5182e8408Ted Kremenek   _EGLDisplay *disp = data;
2805e03fcb5420c33207433dd6f800588e256dd9bdbTed Kremenek   struct dri2_egl_image *dri2_img;
2815e03fcb5420c33207433dd6f800588e256dd9bdbTed Kremenek   _EGLImage *img;
2825e03fcb5420c33207433dd6f800588e256dd9bdbTed Kremenek
2835e03fcb5420c33207433dd6f800588e256dd9bdbTed Kremenek   (void) screen;
2848cc13ea74fea1c04042a2f4087665bc5182e8408Ted Kremenek
2852ded35a576e3899553ea0ccfcbf5cbdb3d8cf664Ted Kremenek   img = _eglLookupImage(image, disp);
2862ded35a576e3899553ea0ccfcbf5cbdb3d8cf664Ted Kremenek   if (img == NULL) {
2872ded35a576e3899553ea0ccfcbf5cbdb3d8cf664Ted Kremenek      _eglError(EGL_BAD_PARAMETER, "dri2_lookup_egl_image");
2882ded35a576e3899553ea0ccfcbf5cbdb3d8cf664Ted Kremenek      return NULL;
289dbfe41acda3078f8fe566318c0097f7ae683c6bbTed Kremenek   }
290dbfe41acda3078f8fe566318c0097f7ae683c6bbTed Kremenek
291dbfe41acda3078f8fe566318c0097f7ae683c6bbTed Kremenek   dri2_img = dri2_egl_image(image);
292dbfe41acda3078f8fe566318c0097f7ae683c6bbTed Kremenek
293dbfe41acda3078f8fe566318c0097f7ae683c6bbTed Kremenek   return dri2_img->dri_image;
294dbfe41acda3078f8fe566318c0097f7ae683c6bbTed Kremenek}
295dbfe41acda3078f8fe566318c0097f7ae683c6bbTed Kremenek
296dbfe41acda3078f8fe566318c0097f7ae683c6bbTed Kremenekconst __DRIimageLookupExtension image_lookup_extension = {
297dbfe41acda3078f8fe566318c0097f7ae683c6bbTed Kremenek   { __DRI_IMAGE_LOOKUP, 1 },
298dbfe41acda3078f8fe566318c0097f7ae683c6bbTed Kremenek   dri2_lookup_egl_image
299dbfe41acda3078f8fe566318c0097f7ae683c6bbTed Kremenek};
300dbfe41acda3078f8fe566318c0097f7ae683c6bbTed Kremenek
301dbfe41acda3078f8fe566318c0097f7ae683c6bbTed Kremenekstatic const char dri_driver_path[] = DEFAULT_DRIVER_DIR;
302dbfe41acda3078f8fe566318c0097f7ae683c6bbTed Kremenek
303dbfe41acda3078f8fe566318c0097f7ae683c6bbTed Kremenekstruct dri2_extension_match {
304dbfe41acda3078f8fe566318c0097f7ae683c6bbTed Kremenek   const char *name;
305dbfe41acda3078f8fe566318c0097f7ae683c6bbTed Kremenek   int version;
30699c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek   int offset;
30799c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek};
30899c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
30999c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenekstatic struct dri2_extension_match dri2_driver_extensions[] = {
31099c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek   { __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) },
31199c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek   { __DRI_DRI2, 2, offsetof(struct dri2_egl_display, dri2) },
31299c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek   { NULL, 0, 0 }
31399c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek};
31499c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
31599c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenekstatic struct dri2_extension_match dri2_core_extensions[] = {
31699c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek   { __DRI2_FLUSH, 1, offsetof(struct dri2_egl_display, flush) },
31799c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek   { __DRI_TEX_BUFFER, 2, offsetof(struct dri2_egl_display, tex_buffer) },
31899c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek   { __DRI_IMAGE, 1, offsetof(struct dri2_egl_display, image) },
31999c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek   { NULL, 0, 0 }
32099c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek};
32199c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek
32299c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenekstatic struct dri2_extension_match swrast_driver_extensions[] = {
32399c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek   { __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) },
32499c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek   { __DRI_SWRAST, 2, offsetof(struct dri2_egl_display, swrast) },
32599c6ad3f22b865d0f4cce52bc36904403c9ed4c4Ted Kremenek   { NULL, 0, 0 }
326b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek};
3276a6719a3a11087b48d9f1a4eb08b3bd43cb05a65Ted Kremenek
328b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenekstatic struct dri2_extension_match swrast_core_extensions[] = {
329b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek   { __DRI_TEX_BUFFER, 2, offsetof(struct dri2_egl_display, tex_buffer) },
3306a6719a3a11087b48d9f1a4eb08b3bd43cb05a65Ted Kremenek   { NULL, 0, 0 }
3316a6719a3a11087b48d9f1a4eb08b3bd43cb05a65Ted Kremenek};
3326a6719a3a11087b48d9f1a4eb08b3bd43cb05a65Ted Kremenek
3336a6719a3a11087b48d9f1a4eb08b3bd43cb05a65Ted Kremenekstatic EGLBoolean
3346a6719a3a11087b48d9f1a4eb08b3bd43cb05a65Ted Kremenekdri2_bind_extensions(struct dri2_egl_display *dri2_dpy,
335b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek		     struct dri2_extension_match *matches,
336b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek		     const __DRIextension **extensions)
337b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek{
338b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek   int i, j, ret = EGL_TRUE;
339b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek   void *field;
340b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek
341b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek   for (i = 0; extensions[i]; i++) {
342b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek      _eglLog(_EGL_DEBUG, "DRI2: found extension `%s'", extensions[i]->name);
343b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek      for (j = 0; matches[j].name; j++) {
344b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek	 if (strcmp(extensions[i]->name, matches[j].name) == 0 &&
34505a2378c708688c8ef498a5cea40ed7f5db15fa5Ted Kremenek	     extensions[i]->version >= matches[j].version) {
34605a2378c708688c8ef498a5cea40ed7f5db15fa5Ted Kremenek	    field = ((char *) dri2_dpy + matches[j].offset);
34700a3a5f024ac54088ab887712b292171188064f0Ted Kremenek	    *(const __DRIextension **) field = extensions[i];
34800a3a5f024ac54088ab887712b292171188064f0Ted Kremenek	    _eglLog(_EGL_INFO, "DRI2: found extension %s version %d",
34900a3a5f024ac54088ab887712b292171188064f0Ted Kremenek		    extensions[i]->name, extensions[i]->version);
35000a3a5f024ac54088ab887712b292171188064f0Ted Kremenek	 }
35100a3a5f024ac54088ab887712b292171188064f0Ted Kremenek      }
35200a3a5f024ac54088ab887712b292171188064f0Ted Kremenek   }
35300a3a5f024ac54088ab887712b292171188064f0Ted Kremenek
35400a3a5f024ac54088ab887712b292171188064f0Ted Kremenek   for (j = 0; matches[j].name; j++) {
35500a3a5f024ac54088ab887712b292171188064f0Ted Kremenek      field = ((char *) dri2_dpy + matches[j].offset);
35600a3a5f024ac54088ab887712b292171188064f0Ted Kremenek      if (*(const __DRIextension **) field == NULL) {
35705a2378c708688c8ef498a5cea40ed7f5db15fa5Ted Kremenek	 _eglLog(_EGL_FATAL, "DRI2: did not find extension %s version %d",
358b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek		 matches[j].name, matches[j].version);
3590d093d3005dd583675a45a85bd688063572cc8afTed Kremenek	 ret = EGL_FALSE;
3600d093d3005dd583675a45a85bd688063572cc8afTed Kremenek      }
361512c913a6f93d225faacdb8e20308f5c4065c3ebTed Kremenek   }
362b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek
363aed9b6ac2ed0013133e4d4aebf2fad2ccd27f3e6Ted Kremenek   return ret;
364b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek}
365aed9b6ac2ed0013133e4d4aebf2fad2ccd27f3e6Ted Kremenek
366aa1c4e5a6b87b62d991c55a0d4522bcd778068d7Ted Kremenekstatic const __DRIextension **
367b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenekdri2_open_driver(_EGLDisplay *disp)
36805a2378c708688c8ef498a5cea40ed7f5db15fa5Ted Kremenek{
3690d093d3005dd583675a45a85bd688063572cc8afTed Kremenek   struct dri2_egl_display *dri2_dpy = disp->DriverData;
3700d093d3005dd583675a45a85bd688063572cc8afTed Kremenek   const __DRIextension **extensions;
3710d093d3005dd583675a45a85bd688063572cc8afTed Kremenek   char path[PATH_MAX], *search_paths, *p, *next, *end;
372b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek
3730d093d3005dd583675a45a85bd688063572cc8afTed Kremenek   search_paths = NULL;
3740d093d3005dd583675a45a85bd688063572cc8afTed Kremenek   if (geteuid() == getuid()) {
3750d093d3005dd583675a45a85bd688063572cc8afTed Kremenek      /* don't allow setuid apps to use LIBGL_DRIVERS_PATH */
376b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek      search_paths = getenv("LIBGL_DRIVERS_PATH");
377aed9b6ac2ed0013133e4d4aebf2fad2ccd27f3e6Ted Kremenek   }
378aa1c4e5a6b87b62d991c55a0d4522bcd778068d7Ted Kremenek   if (search_paths == NULL)
379b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek      search_paths = DEFAULT_DRIVER_DIR;
38005a2378c708688c8ef498a5cea40ed7f5db15fa5Ted Kremenek
381aed9b6ac2ed0013133e4d4aebf2fad2ccd27f3e6Ted Kremenek   dri2_dpy->driver = NULL;
382aa1c4e5a6b87b62d991c55a0d4522bcd778068d7Ted Kremenek   end = search_paths + strlen(search_paths);
383b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek   for (p = search_paths; p < end && dri2_dpy->driver == NULL; p = next + 1) {
384b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek      int len;
385aed9b6ac2ed0013133e4d4aebf2fad2ccd27f3e6Ted Kremenek      next = strchr(p, ':');
38605a2378c708688c8ef498a5cea40ed7f5db15fa5Ted Kremenek      if (next == NULL)
38705a2378c708688c8ef498a5cea40ed7f5db15fa5Ted Kremenek         next = end;
38877349cb20bfd7069d081f84c91975bfa8ef60a32Ted Kremenek
389aed9b6ac2ed0013133e4d4aebf2fad2ccd27f3e6Ted Kremenek      len = next - p;
390aa1c4e5a6b87b62d991c55a0d4522bcd778068d7Ted Kremenek#if GLX_USE_TLS
391b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek      snprintf(path, sizeof path,
392b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek	       "%.*s/tls/%s_dri.so", len, p, dri2_dpy->driver_name);
393aed9b6ac2ed0013133e4d4aebf2fad2ccd27f3e6Ted Kremenek      dri2_dpy->driver = dlopen(path, RTLD_NOW | RTLD_GLOBAL);
394aa1c4e5a6b87b62d991c55a0d4522bcd778068d7Ted Kremenek#endif
395b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek      if (dri2_dpy->driver == NULL) {
396b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek	 snprintf(path, sizeof path,
397aa1c4e5a6b87b62d991c55a0d4522bcd778068d7Ted Kremenek		  "%.*s/%s_dri.so", len, p, dri2_dpy->driver_name);
398240f1f00dda1d481276ea872fe8f8851581a7e6bTed Kremenek	 dri2_dpy->driver = dlopen(path, RTLD_NOW | RTLD_GLOBAL);
399b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek	 if (dri2_dpy->driver == NULL)
400b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek	    _eglLog(_EGL_DEBUG, "failed to open %s: %s\n", path, dlerror());
401b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek      }
402b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek   }
403aed9b6ac2ed0013133e4d4aebf2fad2ccd27f3e6Ted Kremenek
404aed9b6ac2ed0013133e4d4aebf2fad2ccd27f3e6Ted Kremenek   if (dri2_dpy->driver == NULL) {
405aa1c4e5a6b87b62d991c55a0d4522bcd778068d7Ted Kremenek      _eglLog(_EGL_WARNING,
406aa1c4e5a6b87b62d991c55a0d4522bcd778068d7Ted Kremenek	      "DRI2: failed to open %s (search paths %s)",
407aa1c4e5a6b87b62d991c55a0d4522bcd778068d7Ted Kremenek	      dri2_dpy->driver_name, search_paths);
408aa1c4e5a6b87b62d991c55a0d4522bcd778068d7Ted Kremenek      return NULL;
409aa1c4e5a6b87b62d991c55a0d4522bcd778068d7Ted Kremenek   }
410aa1c4e5a6b87b62d991c55a0d4522bcd778068d7Ted Kremenek
411aa1c4e5a6b87b62d991c55a0d4522bcd778068d7Ted Kremenek   _eglLog(_EGL_DEBUG, "DRI2: dlopen(%s)", path);
412aa1c4e5a6b87b62d991c55a0d4522bcd778068d7Ted Kremenek   extensions = dlsym(dri2_dpy->driver, __DRI_DRIVER_EXTENSIONS);
413b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek   if (extensions == NULL) {
414aa1c4e5a6b87b62d991c55a0d4522bcd778068d7Ted Kremenek      _eglLog(_EGL_WARNING,
415b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek	      "DRI2: driver exports no extensions (%s)", dlerror());
416b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek      dlclose(dri2_dpy->driver);
417aed9b6ac2ed0013133e4d4aebf2fad2ccd27f3e6Ted Kremenek   }
418aed9b6ac2ed0013133e4d4aebf2fad2ccd27f3e6Ted Kremenek
419aed9b6ac2ed0013133e4d4aebf2fad2ccd27f3e6Ted Kremenek   return extensions;
420aed9b6ac2ed0013133e4d4aebf2fad2ccd27f3e6Ted Kremenek}
421aed9b6ac2ed0013133e4d4aebf2fad2ccd27f3e6Ted Kremenek
422b387a3f23e423d62c053be86294b703da1d1a222Ted KremenekEGLBoolean
423aed9b6ac2ed0013133e4d4aebf2fad2ccd27f3e6Ted Kremenekdri2_load_driver(_EGLDisplay *disp)
424aed9b6ac2ed0013133e4d4aebf2fad2ccd27f3e6Ted Kremenek{
425b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek   struct dri2_egl_display *dri2_dpy = disp->DriverData;
426aed9b6ac2ed0013133e4d4aebf2fad2ccd27f3e6Ted Kremenek   const __DRIextension **extensions;
427aed9b6ac2ed0013133e4d4aebf2fad2ccd27f3e6Ted Kremenek
428b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek   extensions = dri2_open_driver(disp);
429aed9b6ac2ed0013133e4d4aebf2fad2ccd27f3e6Ted Kremenek   if (!extensions)
430aed9b6ac2ed0013133e4d4aebf2fad2ccd27f3e6Ted Kremenek      return EGL_FALSE;
431b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek
4320e561a3e6755c4f248a8bb05d49071ddf4f2ef7bTed Kremenek   if (!dri2_bind_extensions(dri2_dpy, dri2_driver_extensions, extensions)) {
4335c684c4be01fb98077a9b5e07ca1fdc01d8d97cbTed Kremenek      dlclose(dri2_dpy->driver);
4340e561a3e6755c4f248a8bb05d49071ddf4f2ef7bTed Kremenek      return EGL_FALSE;
4355c684c4be01fb98077a9b5e07ca1fdc01d8d97cbTed Kremenek   }
436b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek
4374a4e524afef40d6f3ddb25d0e407c814e4ca56a8Ted Kremenek   return EGL_TRUE;
4384a4e524afef40d6f3ddb25d0e407c814e4ca56a8Ted Kremenek}
4394a4e524afef40d6f3ddb25d0e407c814e4ca56a8Ted Kremenek
4409dca062461a6244cf0f733346657fa3eee853f9bTed KremenekEGLBoolean
441b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenekdri2_load_driver_swrast(_EGLDisplay *disp)
442b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek{
443b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek   struct dri2_egl_display *dri2_dpy = disp->DriverData;
444b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek   const __DRIextension **extensions;
445ef44bfb9d0f15ba0391f8346c9f01355fb450a09Ted Kremenek
446ef44bfb9d0f15ba0391f8346c9f01355fb450a09Ted Kremenek   dri2_dpy->driver_name = "swrast";
447ef44bfb9d0f15ba0391f8346c9f01355fb450a09Ted Kremenek   extensions = dri2_open_driver(disp);
448ef44bfb9d0f15ba0391f8346c9f01355fb450a09Ted Kremenek
449ef44bfb9d0f15ba0391f8346c9f01355fb450a09Ted Kremenek   if (!extensions)
450ef44bfb9d0f15ba0391f8346c9f01355fb450a09Ted Kremenek      return EGL_FALSE;
451ef44bfb9d0f15ba0391f8346c9f01355fb450a09Ted Kremenek
452ef44bfb9d0f15ba0391f8346c9f01355fb450a09Ted Kremenek   if (!dri2_bind_extensions(dri2_dpy, swrast_driver_extensions, extensions)) {
453ef44bfb9d0f15ba0391f8346c9f01355fb450a09Ted Kremenek      dlclose(dri2_dpy->driver);
454ef44bfb9d0f15ba0391f8346c9f01355fb450a09Ted Kremenek      return EGL_FALSE;
455ef44bfb9d0f15ba0391f8346c9f01355fb450a09Ted Kremenek   }
456ef44bfb9d0f15ba0391f8346c9f01355fb450a09Ted Kremenek
457ef44bfb9d0f15ba0391f8346c9f01355fb450a09Ted Kremenek   return EGL_TRUE;
458b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek}
459b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek
460b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenekvoid
461aa1c4e5a6b87b62d991c55a0d4522bcd778068d7Ted Kremenekdri2_setup_screen(_EGLDisplay *disp)
462b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek{
463de43424560f1a744de6214dab6bbee28ad8437f5Ted Kremenek   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
464de43424560f1a744de6214dab6bbee28ad8437f5Ted Kremenek   unsigned int api_mask;
465aa1c4e5a6b87b62d991c55a0d4522bcd778068d7Ted Kremenek
466de43424560f1a744de6214dab6bbee28ad8437f5Ted Kremenek   if (dri2_dpy->dri2) {
467de43424560f1a744de6214dab6bbee28ad8437f5Ted Kremenek      api_mask = dri2_dpy->dri2->getAPIMask(dri2_dpy->dri_screen);
46855deb97341819080d6d127d29e25b9502e4f2e3cTed Kremenek   } else {
46955deb97341819080d6d127d29e25b9502e4f2e3cTed Kremenek      assert(dri2_dpy->swrast);
47055deb97341819080d6d127d29e25b9502e4f2e3cTed Kremenek      api_mask = 1 << __DRI_API_OPENGL | 1 << __DRI_API_GLES | 1 << __DRI_API_GLES2;
471b9308372e0d40c85cb573c4982fdf5089d89ab6dTed Kremenek   }
472b9308372e0d40c85cb573c4982fdf5089d89ab6dTed Kremenek
473b9308372e0d40c85cb573c4982fdf5089d89ab6dTed Kremenek   disp->ClientAPIs = 0;
474b9308372e0d40c85cb573c4982fdf5089d89ab6dTed Kremenek   if (api_mask & (1 <<__DRI_API_OPENGL))
475b9308372e0d40c85cb573c4982fdf5089d89ab6dTed Kremenek      disp->ClientAPIs |= EGL_OPENGL_BIT;
476b9308372e0d40c85cb573c4982fdf5089d89ab6dTed Kremenek   if (api_mask & (1 <<__DRI_API_GLES))
477b9308372e0d40c85cb573c4982fdf5089d89ab6dTed Kremenek      disp->ClientAPIs |= EGL_OPENGL_ES_BIT;
47855deb97341819080d6d127d29e25b9502e4f2e3cTed Kremenek   if (api_mask & (1 << __DRI_API_GLES2))
479b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek      disp->ClientAPIs |= EGL_OPENGL_ES2_BIT;
480aa1c4e5a6b87b62d991c55a0d4522bcd778068d7Ted Kremenek
481b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek   assert(dri2_dpy->dri2 || dri2_dpy->swrast);
482b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek   disp->Extensions.KHR_surfaceless_context = EGL_TRUE;
483b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek
484b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek   if (dri2_dpy->dri2 && dri2_dpy->dri2->base.version >= 3) {
485b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek      disp->Extensions.KHR_create_context = EGL_TRUE;
486b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek
487b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek      if (dri2_dpy->robustness)
488b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek         disp->Extensions.EXT_create_context_robustness = EGL_TRUE;
489aa1c4e5a6b87b62d991c55a0d4522bcd778068d7Ted Kremenek   }
490b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek
491b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek   if (dri2_dpy->image) {
492b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek      disp->Extensions.MESA_drm_image = EGL_TRUE;
493b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek      disp->Extensions.KHR_image_base = EGL_TRUE;
49402737ed29d7fff2206f7c7ee958cdf0665e35542Ted Kremenek      disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE;
49502737ed29d7fff2206f7c7ee958cdf0665e35542Ted Kremenek   }
49602737ed29d7fff2206f7c7ee958cdf0665e35542Ted Kremenek}
497b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek
498aa1c4e5a6b87b62d991c55a0d4522bcd778068d7Ted KremenekEGLBoolean
499b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenekdri2_create_screen(_EGLDisplay *disp)
500b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek{
501aa1c4e5a6b87b62d991c55a0d4522bcd778068d7Ted Kremenek   const __DRIextension **extensions;
502aa1c4e5a6b87b62d991c55a0d4522bcd778068d7Ted Kremenek   struct dri2_egl_display *dri2_dpy;
503aa1c4e5a6b87b62d991c55a0d4522bcd778068d7Ted Kremenek
504b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek   dri2_dpy = disp->DriverData;
505b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek
506b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek   if (dri2_dpy->dri2) {
507ffe0f43806d4823271c2406c1fccc2373115c36aTed Kremenek      dri2_dpy->dri_screen =
508ffe0f43806d4823271c2406c1fccc2373115c36aTed Kremenek         dri2_dpy->dri2->createNewScreen(0, dri2_dpy->fd, dri2_dpy->extensions,
509d8e9f0dc737133d4e8342f39389064620f5a7f8fTed Kremenek				         &dri2_dpy->driver_configs, disp);
5109ef1ec98a8fc17e7560e07641184bc4daee39b46Ted Kremenek   } else {
5114a4e524afef40d6f3ddb25d0e407c814e4ca56a8Ted Kremenek      assert(dri2_dpy->swrast);
5129ef1ec98a8fc17e7560e07641184bc4daee39b46Ted Kremenek      dri2_dpy->dri_screen =
5139ef1ec98a8fc17e7560e07641184bc4daee39b46Ted Kremenek         dri2_dpy->swrast->createNewScreen(0, dri2_dpy->extensions,
5149ef1ec98a8fc17e7560e07641184bc4daee39b46Ted Kremenek                                           &dri2_dpy->driver_configs, disp);
51500a3a5f024ac54088ab887712b292171188064f0Ted Kremenek   }
5169ef1ec98a8fc17e7560e07641184bc4daee39b46Ted Kremenek
51700a3a5f024ac54088ab887712b292171188064f0Ted Kremenek   if (dri2_dpy->dri_screen == NULL) {
518b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek      _eglLog(_EGL_WARNING, "DRI2: failed to create dri screen");
519b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek      return EGL_FALSE;
520aa1c4e5a6b87b62d991c55a0d4522bcd778068d7Ted Kremenek   }
52100a3a5f024ac54088ab887712b292171188064f0Ted Kremenek
522b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek   dri2_dpy->own_dri_screen = 1;
523b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek
524aa1c4e5a6b87b62d991c55a0d4522bcd778068d7Ted Kremenek   extensions = dri2_dpy->core->getExtensions(dri2_dpy->dri_screen);
52500a3a5f024ac54088ab887712b292171188064f0Ted Kremenek
52690e420321f60860f4c4e7a68ca9f7567824b46ecTed Kremenek   if (dri2_dpy->dri2) {
52710c16657eec144def180ee53d1e0249c9ed2b3b5Ted Kremenek      unsigned i;
528aa1c4e5a6b87b62d991c55a0d4522bcd778068d7Ted Kremenek
52900a3a5f024ac54088ab887712b292171188064f0Ted Kremenek      if (!dri2_bind_extensions(dri2_dpy, dri2_core_extensions, extensions))
530b640b3b5dfccaf259967cb2cb6755c9aa20d4423Ted Kremenek         goto cleanup_dri_screen;
53150d0ac299c641bee9024f3fbae2ea0640898a040Ted Kremenek
532c3055ab39ac3535ffd581d33e21b72133099a6ebTed Kremenek      for (i = 0; extensions[i]; i++) {
53300a3a5f024ac54088ab887712b292171188064f0Ted Kremenek	 if (strcmp(extensions[i]->name, __DRI2_ROBUSTNESS) == 0) {
534c3055ab39ac3535ffd581d33e21b72133099a6ebTed Kremenek            dri2_dpy->robustness = (__DRIrobustnessExtension *) extensions[i];
535c3055ab39ac3535ffd581d33e21b72133099a6ebTed Kremenek	 }
536aa1c4e5a6b87b62d991c55a0d4522bcd778068d7Ted Kremenek      }
537692416c214a3b234236dedcf875735a9cc29e90bTed Kremenek   } else {
5384a4e524afef40d6f3ddb25d0e407c814e4ca56a8Ted Kremenek      assert(dri2_dpy->swrast);
5394a4e524afef40d6f3ddb25d0e407c814e4ca56a8Ted Kremenek      if (!dri2_bind_extensions(dri2_dpy, swrast_core_extensions, extensions))
540692416c214a3b234236dedcf875735a9cc29e90bTed Kremenek         goto cleanup_dri_screen;
541aa1c4e5a6b87b62d991c55a0d4522bcd778068d7Ted Kremenek   }
542692416c214a3b234236dedcf875735a9cc29e90bTed Kremenek
543aa1c4e5a6b87b62d991c55a0d4522bcd778068d7Ted Kremenek   dri2_setup_screen(disp);
544aa1c4e5a6b87b62d991c55a0d4522bcd778068d7Ted Kremenek
545aa1c4e5a6b87b62d991c55a0d4522bcd778068d7Ted Kremenek   return EGL_TRUE;
54600a3a5f024ac54088ab887712b292171188064f0Ted Kremenek
547aa1c4e5a6b87b62d991c55a0d4522bcd778068d7Ted Kremenek cleanup_dri_screen:
54800a3a5f024ac54088ab887712b292171188064f0Ted Kremenek   dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
549aa1c4e5a6b87b62d991c55a0d4522bcd778068d7Ted Kremenek
550692416c214a3b234236dedcf875735a9cc29e90bTed Kremenek   return EGL_FALSE;
5513f916501c91d3f6f37b1d43276c440343f9454f6Ted Kremenek}
5523f916501c91d3f6f37b1d43276c440343f9454f6Ted Kremenek
5533f916501c91d3f6f37b1d43276c440343f9454f6Ted Kremenek/**
5543f916501c91d3f6f37b1d43276c440343f9454f6Ted Kremenek * Called via eglInitialize(), GLX_drv->API.Initialize().
5553f916501c91d3f6f37b1d43276c440343f9454f6Ted Kremenek */
5563f916501c91d3f6f37b1d43276c440343f9454f6Ted Kremenekstatic EGLBoolean
5573f916501c91d3f6f37b1d43276c440343f9454f6Ted Kremenekdri2_initialize(_EGLDriver *drv, _EGLDisplay *disp)
55800a3a5f024ac54088ab887712b292171188064f0Ted Kremenek{
5593f916501c91d3f6f37b1d43276c440343f9454f6Ted Kremenek   /* not until swrast_dri is supported */
5603f916501c91d3f6f37b1d43276c440343f9454f6Ted Kremenek   if (disp->Options.UseFallback)
56100a3a5f024ac54088ab887712b292171188064f0Ted Kremenek      return EGL_FALSE;
56250d0ac299c641bee9024f3fbae2ea0640898a040Ted Kremenek
563de43424560f1a744de6214dab6bbee28ad8437f5Ted Kremenek   switch (disp->Platform) {
564330dddd19406f9cc227e59e0bb0a36ecdc52915eTed Kremenek#ifdef HAVE_X11_PLATFORM
565330dddd19406f9cc227e59e0bb0a36ecdc52915eTed Kremenek   case _EGL_PLATFORM_X11:
56600a3a5f024ac54088ab887712b292171188064f0Ted Kremenek      if (disp->Options.TestOnly)
567de43424560f1a744de6214dab6bbee28ad8437f5Ted Kremenek         return EGL_TRUE;
56805a2378c708688c8ef498a5cea40ed7f5db15fa5Ted Kremenek      return dri2_initialize_x11(drv, disp);
569aed9b6ac2ed0013133e4d4aebf2fad2ccd27f3e6Ted Kremenek#endif
570b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek
57172fc3b30d775a6b720dd0dd87aa853226f0625ddChris Lattner#ifdef HAVE_LIBUDEV
57272fc3b30d775a6b720dd0dd87aa853226f0625ddChris Lattner#ifdef HAVE_DRM_PLATFORM
573d065d6080f0620bb80b933f3f5d52d37bb2ea770Ted Kremenek   case _EGL_PLATFORM_DRM:
574      if (disp->Options.TestOnly)
575         return EGL_TRUE;
576      return dri2_initialize_drm(drv, disp);
577#endif
578#ifdef HAVE_WAYLAND_PLATFORM
579   case _EGL_PLATFORM_WAYLAND:
580      if (disp->Options.TestOnly)
581         return EGL_TRUE;
582      return dri2_initialize_wayland(drv, disp);
583#endif
584#endif
585#ifdef HAVE_ANDROID_PLATFORM
586   case _EGL_PLATFORM_ANDROID:
587      if (disp->Options.TestOnly)
588         return EGL_TRUE;
589      return dri2_initialize_android(drv, disp);
590#endif
591
592   default:
593      return EGL_FALSE;
594   }
595}
596
597/**
598 * Called via eglTerminate(), drv->API.Terminate().
599 */
600static EGLBoolean
601dri2_terminate(_EGLDriver *drv, _EGLDisplay *disp)
602{
603   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
604
605   _eglReleaseDisplayResources(drv, disp);
606   _eglCleanupDisplay(disp);
607
608   if (dri2_dpy->own_dri_screen)
609      dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
610   if (dri2_dpy->fd)
611      close(dri2_dpy->fd);
612   if (dri2_dpy->driver)
613      dlclose(dri2_dpy->driver);
614   if (dri2_dpy->device_name)
615      free(dri2_dpy->device_name);
616
617   if (disp->PlatformDisplay == NULL) {
618      switch (disp->Platform) {
619#ifdef HAVE_X11_PLATFORM
620      case _EGL_PLATFORM_X11:
621         xcb_disconnect(dri2_dpy->conn);
622         break;
623#endif
624#ifdef HAVE_DRM_PLATFORM
625      case _EGL_PLATFORM_DRM:
626         if (dri2_dpy->own_device) {
627            gbm_device_destroy(&dri2_dpy->gbm_dri->base.base);
628         }
629         break;
630#endif
631      default:
632         break;
633      }
634   }
635
636   free(dri2_dpy);
637   disp->DriverData = NULL;
638
639   return EGL_TRUE;
640}
641
642
643/**
644 * Called via eglCreateContext(), drv->API.CreateContext().
645 */
646static _EGLContext *
647dri2_create_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
648		    _EGLContext *share_list, const EGLint *attrib_list)
649{
650   struct dri2_egl_context *dri2_ctx;
651   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
652   struct dri2_egl_context *dri2_ctx_shared = dri2_egl_context(share_list);
653   __DRIcontext *shared =
654      dri2_ctx_shared ? dri2_ctx_shared->dri_context : NULL;
655   struct dri2_egl_config *dri2_config = dri2_egl_config(conf);
656   const __DRIconfig *dri_config;
657   int api;
658
659   (void) drv;
660
661   dri2_ctx = malloc(sizeof *dri2_ctx);
662   if (!dri2_ctx) {
663      _eglError(EGL_BAD_ALLOC, "eglCreateContext");
664      return NULL;
665   }
666
667   if (!_eglInitContext(&dri2_ctx->base, disp, conf, attrib_list))
668      goto cleanup;
669
670   switch (dri2_ctx->base.ClientAPI) {
671   case EGL_OPENGL_ES_API:
672      switch (dri2_ctx->base.ClientMajorVersion) {
673      case 1:
674         api = __DRI_API_GLES;
675         break;
676      case 2:
677      case 3:
678         api = __DRI_API_GLES2;
679         break;
680      default:
681	 _eglError(EGL_BAD_PARAMETER, "eglCreateContext");
682	 return NULL;
683      }
684      break;
685   case EGL_OPENGL_API:
686      if ((dri2_ctx->base.ClientMajorVersion >= 4
687           || (dri2_ctx->base.ClientMajorVersion == 3
688               && dri2_ctx->base.ClientMinorVersion >= 2))
689          && dri2_ctx->base.Profile == EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR)
690         api = __DRI_API_OPENGL_CORE;
691      else
692         api = __DRI_API_OPENGL;
693      break;
694   default:
695      _eglError(EGL_BAD_PARAMETER, "eglCreateContext");
696      return NULL;
697   }
698
699   if (conf != NULL) {
700      /* The config chosen here isn't necessarily
701       * used for surfaces later.
702       * A pixmap surface will use the single config.
703       * This opportunity depends on disabling the
704       * doubleBufferMode check in
705       * src/mesa/main/context.c:check_compatible()
706       */
707      if (dri2_config->dri_double_config)
708         dri_config = dri2_config->dri_double_config;
709      else
710         dri_config = dri2_config->dri_single_config;
711
712      /* EGL_WINDOW_BIT is set only when there is a dri_double_config.  This
713       * makes sure the back buffer will always be used.
714       */
715      if (conf->SurfaceType & EGL_WINDOW_BIT)
716         dri2_ctx->base.WindowRenderBuffer = EGL_BACK_BUFFER;
717   }
718   else
719      dri_config = NULL;
720
721   if (dri2_dpy->dri2) {
722      if (dri2_dpy->dri2->base.version >= 3) {
723         unsigned error;
724         unsigned num_attribs = 0;
725         uint32_t ctx_attribs[8];
726
727         ctx_attribs[num_attribs++] = __DRI_CTX_ATTRIB_MAJOR_VERSION;
728         ctx_attribs[num_attribs++] = dri2_ctx->base.ClientMajorVersion;
729         ctx_attribs[num_attribs++] = __DRI_CTX_ATTRIB_MINOR_VERSION;
730         ctx_attribs[num_attribs++] = dri2_ctx->base.ClientMinorVersion;
731
732         if (dri2_ctx->base.Flags != 0) {
733            /* If the implementation doesn't support the __DRI2_ROBUSTNESS
734             * extension, don't even try to send it the robust-access flag.
735             * It may explode.  Instead, generate the required EGL error here.
736             */
737            if ((dri2_ctx->base.Flags & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR) != 0
738                && !dri2_dpy->robustness) {
739               _eglError(EGL_BAD_MATCH, "eglCreateContext");
740               goto cleanup;
741            }
742
743            ctx_attribs[num_attribs++] = __DRI_CTX_ATTRIB_FLAGS;
744            ctx_attribs[num_attribs++] = dri2_ctx->base.Flags;
745         }
746
747         if (dri2_ctx->base.ResetNotificationStrategy != EGL_NO_RESET_NOTIFICATION_KHR) {
748            /* If the implementation doesn't support the __DRI2_ROBUSTNESS
749             * extension, don't even try to send it a reset strategy.  It may
750             * explode.  Instead, generate the required EGL error here.
751             */
752            if (!dri2_dpy->robustness) {
753               _eglError(EGL_BAD_CONFIG, "eglCreateContext");
754               goto cleanup;
755            }
756
757            ctx_attribs[num_attribs++] = __DRI_CTX_ATTRIB_RESET_STRATEGY;
758            ctx_attribs[num_attribs++] = __DRI_CTX_RESET_LOSE_CONTEXT;
759         }
760
761         assert(num_attribs <= ARRAY_SIZE(ctx_attribs));
762
763	 dri2_ctx->dri_context =
764	    dri2_dpy->dri2->createContextAttribs(dri2_dpy->dri_screen,
765                                                 api,
766                                                 dri_config,
767                                                 shared,
768                                                 num_attribs / 2,
769                                                 ctx_attribs,
770                                                 & error,
771                                                 dri2_ctx);
772      } else {
773	 dri2_ctx->dri_context =
774	    dri2_dpy->dri2->createNewContextForAPI(dri2_dpy->dri_screen,
775						   api,
776						   dri_config,
777                                                   shared,
778						   dri2_ctx);
779      }
780   } else {
781      assert(dri2_dpy->swrast);
782      dri2_ctx->dri_context =
783         dri2_dpy->swrast->createNewContextForAPI(dri2_dpy->dri_screen,
784                                                  api,
785                                                  dri_config,
786                                                  shared,
787                                                  dri2_ctx);
788   }
789
790   if (!dri2_ctx->dri_context)
791      goto cleanup;
792
793   return &dri2_ctx->base;
794
795 cleanup:
796   free(dri2_ctx);
797   return NULL;
798}
799
800/**
801 * Called via eglDestroyContext(), drv->API.DestroyContext().
802 */
803static EGLBoolean
804dri2_destroy_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx)
805{
806   struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
807   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
808
809   if (_eglPutContext(ctx)) {
810      dri2_dpy->core->destroyContext(dri2_ctx->dri_context);
811      free(dri2_ctx);
812   }
813
814   return EGL_TRUE;
815}
816
817/**
818 * Called via eglMakeCurrent(), drv->API.MakeCurrent().
819 */
820static EGLBoolean
821dri2_make_current(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf,
822		  _EGLSurface *rsurf, _EGLContext *ctx)
823{
824   struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
825   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
826   struct dri2_egl_surface *dri2_dsurf = dri2_egl_surface(dsurf);
827   struct dri2_egl_surface *dri2_rsurf = dri2_egl_surface(rsurf);
828   struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
829   _EGLContext *old_ctx;
830   _EGLSurface *old_dsurf, *old_rsurf;
831   __DRIdrawable *ddraw, *rdraw;
832   __DRIcontext *cctx;
833
834   /* make new bindings */
835   if (!_eglBindContext(ctx, dsurf, rsurf, &old_ctx, &old_dsurf, &old_rsurf))
836      return EGL_FALSE;
837
838   /* flush before context switch */
839   if (old_ctx && dri2_drv->glFlush)
840      dri2_drv->glFlush();
841
842   ddraw = (dri2_dsurf) ? dri2_dsurf->dri_drawable : NULL;
843   rdraw = (dri2_rsurf) ? dri2_rsurf->dri_drawable : NULL;
844   cctx = (dri2_ctx) ? dri2_ctx->dri_context : NULL;
845
846   if (old_ctx) {
847      __DRIcontext *old_cctx = dri2_egl_context(old_ctx)->dri_context;
848      dri2_dpy->core->unbindContext(old_cctx);
849   }
850
851   if ((cctx == NULL && ddraw == NULL && rdraw == NULL) ||
852       dri2_dpy->core->bindContext(cctx, ddraw, rdraw)) {
853      if (old_dsurf)
854         drv->API.DestroySurface(drv, disp, old_dsurf);
855      if (old_rsurf)
856         drv->API.DestroySurface(drv, disp, old_rsurf);
857      if (old_ctx)
858         drv->API.DestroyContext(drv, disp, old_ctx);
859
860      return EGL_TRUE;
861   } else {
862      /* undo the previous _eglBindContext */
863      _eglBindContext(old_ctx, old_dsurf, old_rsurf, &ctx, &dsurf, &rsurf);
864      assert(&dri2_ctx->base == ctx &&
865             &dri2_dsurf->base == dsurf &&
866             &dri2_rsurf->base == rsurf);
867
868      _eglPutSurface(dsurf);
869      _eglPutSurface(rsurf);
870      _eglPutContext(ctx);
871
872      _eglPutSurface(old_dsurf);
873      _eglPutSurface(old_rsurf);
874      _eglPutContext(old_ctx);
875
876      return EGL_FALSE;
877   }
878}
879
880/*
881 * Called from eglGetProcAddress() via drv->API.GetProcAddress().
882 */
883static _EGLProc
884dri2_get_proc_address(_EGLDriver *drv, const char *procname)
885{
886   struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
887
888   return dri2_drv->get_proc_address(procname);
889}
890
891static EGLBoolean
892dri2_wait_client(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx)
893{
894   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
895   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(ctx->DrawSurface);
896
897   (void) drv;
898
899   /* FIXME: If EGL allows frontbuffer rendering for window surfaces,
900    * we need to copy fake to real here.*/
901
902   (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable);
903
904   return EGL_TRUE;
905}
906
907static EGLBoolean
908dri2_wait_native(_EGLDriver *drv, _EGLDisplay *disp, EGLint engine)
909{
910   (void) drv;
911   (void) disp;
912
913   if (engine != EGL_CORE_NATIVE_ENGINE)
914      return _eglError(EGL_BAD_PARAMETER, "eglWaitNative");
915   /* glXWaitX(); */
916
917   return EGL_TRUE;
918}
919
920static EGLBoolean
921dri2_bind_tex_image(_EGLDriver *drv,
922		    _EGLDisplay *disp, _EGLSurface *surf, EGLint buffer)
923{
924   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
925   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
926   struct dri2_egl_context *dri2_ctx;
927   _EGLContext *ctx;
928   GLint format, target;
929
930   ctx = _eglGetCurrentContext();
931   dri2_ctx = dri2_egl_context(ctx);
932
933   if (!_eglBindTexImage(drv, disp, surf, buffer))
934      return EGL_FALSE;
935
936   switch (dri2_surf->base.TextureFormat) {
937   case EGL_TEXTURE_RGB:
938      format = __DRI_TEXTURE_FORMAT_RGB;
939      break;
940   case EGL_TEXTURE_RGBA:
941      format = __DRI_TEXTURE_FORMAT_RGBA;
942      break;
943   default:
944      assert(0);
945   }
946
947   switch (dri2_surf->base.TextureTarget) {
948   case EGL_TEXTURE_2D:
949      target = GL_TEXTURE_2D;
950      break;
951   default:
952      assert(0);
953   }
954
955   (*dri2_dpy->tex_buffer->setTexBuffer2)(dri2_ctx->dri_context,
956					  target, format,
957					  dri2_surf->dri_drawable);
958
959   return EGL_TRUE;
960}
961
962static EGLBoolean
963dri2_release_tex_image(_EGLDriver *drv,
964		       _EGLDisplay *disp, _EGLSurface *surf, EGLint buffer)
965{
966#if __DRI_TEX_BUFFER_VERSION >= 3
967   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
968   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
969   struct dri2_egl_context *dri2_ctx;
970   _EGLContext *ctx;
971   GLint  target;
972
973   ctx = _eglGetCurrentContext();
974   dri2_ctx = dri2_egl_context(ctx);
975
976   if (!_eglReleaseTexImage(drv, disp, surf, buffer))
977      return EGL_FALSE;
978
979   switch (dri2_surf->base.TextureTarget) {
980   case EGL_TEXTURE_2D:
981      target = GL_TEXTURE_2D;
982      break;
983   default:
984      assert(0);
985   }
986   if (dri2_dpy->tex_buffer->releaseTexBuffer!=NULL)
987    (*dri2_dpy->tex_buffer->releaseTexBuffer)(dri2_ctx->dri_context,
988                                             target,
989                                             dri2_surf->dri_drawable);
990#endif
991
992   return EGL_TRUE;
993}
994
995static _EGLImage *
996dri2_create_image(_EGLDisplay *disp, __DRIimage *dri_image)
997{
998   struct dri2_egl_image *dri2_img;
999
1000   if (dri_image == NULL) {
1001      _eglError(EGL_BAD_ALLOC, "dri2_create_image");
1002      return NULL;
1003   }
1004
1005   dri2_img = malloc(sizeof *dri2_img);
1006   if (!dri2_img) {
1007      _eglError(EGL_BAD_ALLOC, "dri2_create_image");
1008      return NULL;
1009   }
1010
1011   if (!_eglInitImage(&dri2_img->base, disp)) {
1012      free(dri2_img);
1013      return NULL;
1014   }
1015
1016   dri2_img->dri_image = dri_image;
1017
1018   return &dri2_img->base;
1019}
1020
1021static _EGLImage *
1022dri2_create_image_khr_renderbuffer(_EGLDisplay *disp, _EGLContext *ctx,
1023				   EGLClientBuffer buffer,
1024				   const EGLint *attr_list)
1025{
1026   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1027   struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
1028   GLuint renderbuffer = (GLuint) (uintptr_t) buffer;
1029   __DRIimage *dri_image;
1030
1031   if (renderbuffer == 0) {
1032      _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
1033      return EGL_NO_IMAGE_KHR;
1034   }
1035
1036   dri_image =
1037      dri2_dpy->image->createImageFromRenderbuffer(dri2_ctx->dri_context,
1038                                                   renderbuffer, NULL);
1039
1040   return dri2_create_image(disp, dri_image);
1041}
1042
1043static _EGLImage *
1044dri2_create_image_mesa_drm_buffer(_EGLDisplay *disp, _EGLContext *ctx,
1045				  EGLClientBuffer buffer, const EGLint *attr_list)
1046{
1047   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1048   EGLint format, name, pitch, err;
1049   _EGLImageAttribs attrs;
1050   __DRIimage *dri_image;
1051
1052   name = (EGLint) (uintptr_t) buffer;
1053
1054   err = _eglParseImageAttribList(&attrs, disp, attr_list);
1055   if (err != EGL_SUCCESS)
1056      return NULL;
1057
1058   if (attrs.Width <= 0 || attrs.Height <= 0 ||
1059       attrs.DRMBufferStrideMESA <= 0) {
1060      _eglError(EGL_BAD_PARAMETER,
1061		"bad width, height or stride");
1062      return NULL;
1063   }
1064
1065   switch (attrs.DRMBufferFormatMESA) {
1066   case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA:
1067      format = __DRI_IMAGE_FORMAT_ARGB8888;
1068      pitch = attrs.DRMBufferStrideMESA;
1069      break;
1070   default:
1071      _eglError(EGL_BAD_PARAMETER,
1072		"dri2_create_image_khr: unsupported pixmap depth");
1073      return NULL;
1074   }
1075
1076   dri_image =
1077      dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen,
1078					   attrs.Width,
1079					   attrs.Height,
1080					   format,
1081					   name,
1082					   pitch,
1083					   NULL);
1084
1085   return dri2_create_image(disp, dri_image);
1086}
1087
1088#ifdef HAVE_WAYLAND_PLATFORM
1089
1090/* This structure describes how a wl_buffer maps to one or more
1091 * __DRIimages.  A wl_drm_buffer stores the wl_drm format code and the
1092 * offsets and strides of the planes in the buffer.  This table maps a
1093 * wl_drm format code to a description of the planes in the buffer
1094 * that lets us create a __DRIimage for each of the planes. */
1095
1096static const struct wl_drm_components_descriptor {
1097   uint32_t dri_components;
1098   EGLint components;
1099   int nplanes;
1100} wl_drm_components[] = {
1101   { __DRI_IMAGE_COMPONENTS_RGB, EGL_TEXTURE_RGB, 1 },
1102   { __DRI_IMAGE_COMPONENTS_RGBA, EGL_TEXTURE_RGBA, 1 },
1103   { __DRI_IMAGE_COMPONENTS_Y_U_V, EGL_TEXTURE_Y_U_V_WL, 3 },
1104   { __DRI_IMAGE_COMPONENTS_Y_UV, EGL_TEXTURE_Y_UV_WL, 2 },
1105   { __DRI_IMAGE_COMPONENTS_Y_XUXV, EGL_TEXTURE_Y_XUXV_WL, 2 },
1106};
1107
1108static _EGLImage *
1109dri2_create_image_wayland_wl_buffer(_EGLDisplay *disp, _EGLContext *ctx,
1110				    EGLClientBuffer _buffer,
1111				    const EGLint *attr_list)
1112{
1113   struct wl_drm_buffer *buffer = (struct wl_drm_buffer *) _buffer;
1114   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1115   const struct wl_drm_components_descriptor *f;
1116   __DRIimage *dri_image;
1117   _EGLImageAttribs attrs;
1118   EGLint err;
1119   int32_t plane;
1120
1121   if (!wayland_buffer_is_drm(&buffer->buffer))
1122       return NULL;
1123
1124   err = _eglParseImageAttribList(&attrs, disp, attr_list);
1125   plane = attrs.PlaneWL;
1126   if (err != EGL_SUCCESS) {
1127      _eglError(EGL_BAD_PARAMETER, "dri2_create_image_wayland_wl_buffer");
1128      return NULL;
1129   }
1130
1131   f = buffer->driver_format;
1132   if (plane < 0 || plane >= f->nplanes) {
1133      _eglError(EGL_BAD_PARAMETER,
1134                "dri2_create_image_wayland_wl_buffer (plane out of bounds)");
1135      return NULL;
1136   }
1137
1138   dri_image = dri2_dpy->image->fromPlanar(buffer->driver_buffer, plane, NULL);
1139
1140   if (dri_image == NULL) {
1141      _eglError(EGL_BAD_PARAMETER, "dri2_create_image_wayland_wl_buffer");
1142      return NULL;
1143   }
1144
1145   return dri2_create_image(disp, dri_image);
1146}
1147#endif
1148
1149_EGLImage *
1150dri2_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
1151		      _EGLContext *ctx, EGLenum target,
1152		      EGLClientBuffer buffer, const EGLint *attr_list)
1153{
1154   (void) drv;
1155
1156   switch (target) {
1157   case EGL_GL_RENDERBUFFER_KHR:
1158      return dri2_create_image_khr_renderbuffer(disp, ctx, buffer, attr_list);
1159   case EGL_DRM_BUFFER_MESA:
1160      return dri2_create_image_mesa_drm_buffer(disp, ctx, buffer, attr_list);
1161#ifdef HAVE_WAYLAND_PLATFORM
1162   case EGL_WAYLAND_BUFFER_WL:
1163      return dri2_create_image_wayland_wl_buffer(disp, ctx, buffer, attr_list);
1164#endif
1165   default:
1166      _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
1167      return EGL_NO_IMAGE_KHR;
1168   }
1169}
1170
1171static EGLBoolean
1172dri2_destroy_image_khr(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *image)
1173{
1174   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1175   struct dri2_egl_image *dri2_img = dri2_egl_image(image);
1176
1177   (void) drv;
1178
1179   dri2_dpy->image->destroyImage(dri2_img->dri_image);
1180   free(dri2_img);
1181
1182   return EGL_TRUE;
1183}
1184
1185static _EGLImage *
1186dri2_create_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp,
1187			   const EGLint *attr_list)
1188{
1189   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1190   struct dri2_egl_image *dri2_img;
1191   _EGLImageAttribs attrs;
1192   unsigned int dri_use, valid_mask;
1193   int format;
1194   EGLint err = EGL_SUCCESS;
1195
1196   (void) drv;
1197
1198   dri2_img = malloc(sizeof *dri2_img);
1199   if (!dri2_img) {
1200      _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
1201      return EGL_NO_IMAGE_KHR;
1202   }
1203
1204   if (!attr_list) {
1205      err = EGL_BAD_PARAMETER;
1206      goto cleanup_img;
1207   }
1208
1209   if (!_eglInitImage(&dri2_img->base, disp)) {
1210      err = EGL_BAD_PARAMETER;
1211      goto cleanup_img;
1212   }
1213
1214   err = _eglParseImageAttribList(&attrs, disp, attr_list);
1215   if (err != EGL_SUCCESS)
1216      goto cleanup_img;
1217
1218   if (attrs.Width <= 0 || attrs.Height <= 0) {
1219      _eglLog(_EGL_WARNING, "bad width or height (%dx%d)",
1220            attrs.Width, attrs.Height);
1221      goto cleanup_img;
1222   }
1223
1224   switch (attrs.DRMBufferFormatMESA) {
1225   case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA:
1226      format = __DRI_IMAGE_FORMAT_ARGB8888;
1227      break;
1228   default:
1229      _eglLog(_EGL_WARNING, "bad image format value 0x%04x",
1230            attrs.DRMBufferFormatMESA);
1231      goto cleanup_img;
1232   }
1233
1234   valid_mask =
1235      EGL_DRM_BUFFER_USE_SCANOUT_MESA |
1236      EGL_DRM_BUFFER_USE_SHARE_MESA |
1237      EGL_DRM_BUFFER_USE_CURSOR_MESA;
1238   if (attrs.DRMBufferUseMESA & ~valid_mask) {
1239      _eglLog(_EGL_WARNING, "bad image use bit 0x%04x",
1240            attrs.DRMBufferUseMESA & ~valid_mask);
1241      goto cleanup_img;
1242   }
1243
1244   dri_use = 0;
1245   if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SHARE_MESA)
1246      dri_use |= __DRI_IMAGE_USE_SHARE;
1247   if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SCANOUT_MESA)
1248      dri_use |= __DRI_IMAGE_USE_SCANOUT;
1249   if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_CURSOR_MESA)
1250      dri_use |= __DRI_IMAGE_USE_CURSOR;
1251
1252   dri2_img->dri_image =
1253      dri2_dpy->image->createImage(dri2_dpy->dri_screen,
1254				   attrs.Width, attrs.Height,
1255                                   format, dri_use, dri2_img);
1256   if (dri2_img->dri_image == NULL) {
1257      err = EGL_BAD_ALLOC;
1258      goto cleanup_img;
1259   }
1260
1261   return &dri2_img->base;
1262
1263 cleanup_img:
1264   free(dri2_img);
1265   _eglError(err, "dri2_create_drm_image_mesa");
1266
1267   return EGL_NO_IMAGE_KHR;
1268}
1269
1270static EGLBoolean
1271dri2_export_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *img,
1272			  EGLint *name, EGLint *handle, EGLint *stride)
1273{
1274   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1275   struct dri2_egl_image *dri2_img = dri2_egl_image(img);
1276
1277   (void) drv;
1278
1279   if (name && !dri2_dpy->image->queryImage(dri2_img->dri_image,
1280					    __DRI_IMAGE_ATTRIB_NAME, name)) {
1281      _eglError(EGL_BAD_ALLOC, "dri2_export_drm_image_mesa");
1282      return EGL_FALSE;
1283   }
1284
1285   if (handle)
1286      dri2_dpy->image->queryImage(dri2_img->dri_image,
1287				  __DRI_IMAGE_ATTRIB_HANDLE, handle);
1288
1289   if (stride)
1290      dri2_dpy->image->queryImage(dri2_img->dri_image,
1291				  __DRI_IMAGE_ATTRIB_STRIDE, stride);
1292
1293   return EGL_TRUE;
1294}
1295
1296#ifdef HAVE_WAYLAND_PLATFORM
1297
1298static void
1299dri2_wl_reference_buffer(void *user_data, uint32_t name,
1300                         struct wl_drm_buffer *buffer)
1301{
1302   _EGLDisplay *disp = user_data;
1303   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1304   __DRIimage *img;
1305   int i, dri_components = 0;
1306
1307   img = dri2_dpy->image->createImageFromNames(dri2_dpy->dri_screen,
1308                                               buffer->buffer.width,
1309                                               buffer->buffer.height,
1310                                               buffer->format, (int*)&name, 1,
1311                                               buffer->stride,
1312                                               buffer->offset,
1313                                               NULL);
1314
1315   if (img == NULL)
1316      return;
1317
1318   dri2_dpy->image->queryImage(img, __DRI_IMAGE_ATTRIB_COMPONENTS, &dri_components);
1319
1320   buffer->driver_format = NULL;
1321   for (i = 0; i < ARRAY_SIZE(wl_drm_components); i++)
1322      if (wl_drm_components[i].dri_components == dri_components)
1323         buffer->driver_format = &wl_drm_components[i];
1324
1325   if (buffer->driver_format == NULL)
1326      dri2_dpy->image->destroyImage(img);
1327   else
1328      buffer->driver_buffer = img;
1329}
1330
1331static void
1332dri2_wl_release_buffer(void *user_data, struct wl_drm_buffer *buffer)
1333{
1334   _EGLDisplay *disp = user_data;
1335   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1336
1337   dri2_dpy->image->destroyImage(buffer->driver_buffer);
1338}
1339
1340static struct wayland_drm_callbacks wl_drm_callbacks = {
1341	.authenticate = NULL,
1342	.reference_buffer = dri2_wl_reference_buffer,
1343	.release_buffer = dri2_wl_release_buffer
1344};
1345
1346static EGLBoolean
1347dri2_bind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *disp,
1348			     struct wl_display *wl_dpy)
1349{
1350   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1351
1352   (void) drv;
1353
1354   if (dri2_dpy->wl_server_drm)
1355	   return EGL_FALSE;
1356
1357   wl_drm_callbacks.authenticate =
1358      (int(*)(void *, uint32_t)) dri2_dpy->authenticate;
1359
1360   dri2_dpy->wl_server_drm =
1361	   wayland_drm_init(wl_dpy, dri2_dpy->device_name,
1362                            &wl_drm_callbacks, disp);
1363
1364   if (!dri2_dpy->wl_server_drm)
1365	   return EGL_FALSE;
1366
1367   return EGL_TRUE;
1368}
1369
1370static EGLBoolean
1371dri2_unbind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *disp,
1372			       struct wl_display *wl_dpy)
1373{
1374   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
1375
1376   (void) drv;
1377
1378   if (!dri2_dpy->wl_server_drm)
1379	   return EGL_FALSE;
1380
1381   wayland_drm_uninit(dri2_dpy->wl_server_drm);
1382   dri2_dpy->wl_server_drm = NULL;
1383
1384   return EGL_TRUE;
1385}
1386
1387static EGLBoolean
1388dri2_query_wayland_buffer_wl(_EGLDriver *drv, _EGLDisplay *disp,
1389                             struct wl_buffer *_buffer,
1390                             EGLint attribute, EGLint *value)
1391{
1392   struct wl_drm_buffer *buffer = (struct wl_drm_buffer *) _buffer;
1393   const struct wl_drm_components_descriptor *format;
1394
1395   if (!wayland_buffer_is_drm(&buffer->buffer))
1396      return EGL_FALSE;
1397
1398   format = buffer->driver_format;
1399   switch (attribute) {
1400   case EGL_TEXTURE_FORMAT:
1401      *value = format->components;
1402      return EGL_TRUE;
1403   case EGL_WIDTH:
1404      *value = buffer->buffer.width;
1405      break;
1406   case EGL_HEIGHT:
1407      *value = buffer->buffer.height;
1408      break;
1409   }
1410
1411   return EGL_FALSE;
1412}
1413#endif
1414
1415static void
1416dri2_unload(_EGLDriver *drv)
1417{
1418   struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
1419
1420   if (dri2_drv->handle)
1421      dlclose(dri2_drv->handle);
1422   free(dri2_drv);
1423}
1424
1425static EGLBoolean
1426dri2_load(_EGLDriver *drv)
1427{
1428   struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
1429#ifdef HAVE_SHARED_GLAPI
1430#ifdef HAVE_ANDROID_PLATFORM
1431   const char *libname = "libglapi.so";
1432#else
1433   const char *libname = "libglapi.so.0";
1434#endif
1435#else
1436   /*
1437    * Both libGL.so and libglapi.so are glapi providers.  There is no way to
1438    * tell which one to load.
1439    */
1440   const char *libname = NULL;
1441#endif
1442   void *handle;
1443
1444   /* RTLD_GLOBAL to make sure glapi symbols are visible to DRI drivers */
1445   handle = dlopen(libname, RTLD_LAZY | RTLD_GLOBAL);
1446   if (handle) {
1447      dri2_drv->get_proc_address = (_EGLProc (*)(const char *))
1448         dlsym(handle, "_glapi_get_proc_address");
1449      if (!dri2_drv->get_proc_address || !libname) {
1450         /* no need to keep a reference */
1451         dlclose(handle);
1452         handle = NULL;
1453      }
1454   }
1455
1456   /* if glapi is not available, loading DRI drivers will fail */
1457   if (!dri2_drv->get_proc_address) {
1458      _eglLog(_EGL_WARNING, "DRI2: failed to find _glapi_get_proc_address");
1459      return EGL_FALSE;
1460   }
1461
1462   dri2_drv->glFlush = (void (*)(void))
1463      dri2_drv->get_proc_address("glFlush");
1464
1465   dri2_drv->handle = handle;
1466
1467   return EGL_TRUE;
1468}
1469
1470/**
1471 * This is the main entrypoint into the driver, called by libEGL.
1472 * Create a new _EGLDriver object and init its dispatch table.
1473 */
1474_EGLDriver *
1475_eglBuiltInDriverDRI2(const char *args)
1476{
1477   struct dri2_egl_driver *dri2_drv;
1478
1479   (void) args;
1480
1481   dri2_drv = malloc(sizeof *dri2_drv);
1482   if (!dri2_drv)
1483      return NULL;
1484
1485   memset(dri2_drv, 0, sizeof *dri2_drv);
1486
1487   if (!dri2_load(&dri2_drv->base)) {
1488      free(dri2_drv);
1489      return NULL;
1490   }
1491
1492   _eglInitDriverFallbacks(&dri2_drv->base);
1493   dri2_drv->base.API.Initialize = dri2_initialize;
1494   dri2_drv->base.API.Terminate = dri2_terminate;
1495   dri2_drv->base.API.CreateContext = dri2_create_context;
1496   dri2_drv->base.API.DestroyContext = dri2_destroy_context;
1497   dri2_drv->base.API.MakeCurrent = dri2_make_current;
1498   dri2_drv->base.API.GetProcAddress = dri2_get_proc_address;
1499   dri2_drv->base.API.WaitClient = dri2_wait_client;
1500   dri2_drv->base.API.WaitNative = dri2_wait_native;
1501   dri2_drv->base.API.BindTexImage = dri2_bind_tex_image;
1502   dri2_drv->base.API.ReleaseTexImage = dri2_release_tex_image;
1503   dri2_drv->base.API.CreateImageKHR = dri2_create_image_khr;
1504   dri2_drv->base.API.DestroyImageKHR = dri2_destroy_image_khr;
1505   dri2_drv->base.API.CreateDRMImageMESA = dri2_create_drm_image_mesa;
1506   dri2_drv->base.API.ExportDRMImageMESA = dri2_export_drm_image_mesa;
1507#ifdef HAVE_WAYLAND_PLATFORM
1508   dri2_drv->base.API.BindWaylandDisplayWL = dri2_bind_wayland_display_wl;
1509   dri2_drv->base.API.UnbindWaylandDisplayWL = dri2_unbind_wayland_display_wl;
1510   dri2_drv->base.API.QueryWaylandBufferWL = dri2_query_wayland_buffer_wl;
1511#endif
1512
1513   dri2_drv->base.Name = "DRI2";
1514   dri2_drv->base.Unload = dri2_unload;
1515
1516   return &dri2_drv->base;
1517}
1518