2010-02-03 15:18:28 +00:00
|
|
|
/*
|
|
|
|
* Copyright © 2010 Intel Corporation
|
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
|
|
* to deal in the Software without restriction, including without limitation
|
|
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
|
|
*
|
|
|
|
* The above copyright notice and this permission notice (including the next
|
|
|
|
* paragraph) shall be included in all copies or substantial portions of the
|
|
|
|
* Software.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
|
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
|
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
|
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
|
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
|
|
* DEALINGS IN THE SOFTWARE.
|
|
|
|
*
|
|
|
|
* Authors:
|
|
|
|
* Kristian Høgsberg <krh@bitplanet.net>
|
|
|
|
*/
|
|
|
|
|
2014-01-29 02:53:56 +00:00
|
|
|
#define WL_HIDE_DEPRECATED
|
|
|
|
|
2010-02-03 15:18:28 +00:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <limits.h>
|
|
|
|
#include <dlfcn.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <unistd.h>
|
2013-11-10 18:32:01 +00:00
|
|
|
#ifdef HAVE_DRM_PLATFORM
|
2010-02-03 15:18:28 +00:00
|
|
|
#include <xf86drm.h>
|
2013-03-22 13:58:05 +00:00
|
|
|
#include <drm_fourcc.h>
|
2013-11-10 18:32:01 +00:00
|
|
|
#endif
|
2010-02-03 15:18:28 +00:00
|
|
|
#include <GL/gl.h>
|
|
|
|
#include <GL/internal/dri_interface.h>
|
2010-06-03 03:48:06 +01:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
2013-07-18 13:11:25 +01:00
|
|
|
#ifdef HAVE_WAYLAND_PLATFORM
|
|
|
|
#include "wayland-drm.h"
|
2014-01-29 02:53:56 +00:00
|
|
|
#include "wayland-drm-client-protocol.h"
|
2013-07-18 13:11:25 +01:00
|
|
|
#endif
|
|
|
|
|
2014-01-29 02:53:56 +00:00
|
|
|
#include "egl_dri2.h"
|
|
|
|
|
2011-02-03 03:21:13 +00:00
|
|
|
const __DRIuseInvalidateExtension use_invalidate = {
|
2010-06-03 03:48:06 +01:00
|
|
|
{ __DRI_USE_INVALIDATE, 1 }
|
|
|
|
};
|
|
|
|
|
2010-02-03 15:18:28 +00:00
|
|
|
EGLint dri2_to_egl_attribute_map[] = {
|
|
|
|
0,
|
|
|
|
EGL_BUFFER_SIZE, /* __DRI_ATTRIB_BUFFER_SIZE */
|
|
|
|
EGL_LEVEL, /* __DRI_ATTRIB_LEVEL */
|
|
|
|
EGL_RED_SIZE, /* __DRI_ATTRIB_RED_SIZE */
|
|
|
|
EGL_GREEN_SIZE, /* __DRI_ATTRIB_GREEN_SIZE */
|
|
|
|
EGL_BLUE_SIZE, /* __DRI_ATTRIB_BLUE_SIZE */
|
2010-02-10 02:01:04 +00:00
|
|
|
EGL_LUMINANCE_SIZE, /* __DRI_ATTRIB_LUMINANCE_SIZE */
|
2010-02-03 15:18:28 +00:00
|
|
|
EGL_ALPHA_SIZE, /* __DRI_ATTRIB_ALPHA_SIZE */
|
|
|
|
0, /* __DRI_ATTRIB_ALPHA_MASK_SIZE */
|
|
|
|
EGL_DEPTH_SIZE, /* __DRI_ATTRIB_DEPTH_SIZE */
|
|
|
|
EGL_STENCIL_SIZE, /* __DRI_ATTRIB_STENCIL_SIZE */
|
|
|
|
0, /* __DRI_ATTRIB_ACCUM_RED_SIZE */
|
|
|
|
0, /* __DRI_ATTRIB_ACCUM_GREEN_SIZE */
|
|
|
|
0, /* __DRI_ATTRIB_ACCUM_BLUE_SIZE */
|
|
|
|
0, /* __DRI_ATTRIB_ACCUM_ALPHA_SIZE */
|
|
|
|
EGL_SAMPLE_BUFFERS, /* __DRI_ATTRIB_SAMPLE_BUFFERS */
|
|
|
|
EGL_SAMPLES, /* __DRI_ATTRIB_SAMPLES */
|
|
|
|
0, /* __DRI_ATTRIB_RENDER_TYPE, */
|
|
|
|
0, /* __DRI_ATTRIB_CONFIG_CAVEAT */
|
|
|
|
0, /* __DRI_ATTRIB_CONFORMANT */
|
|
|
|
0, /* __DRI_ATTRIB_DOUBLE_BUFFER */
|
|
|
|
0, /* __DRI_ATTRIB_STEREO */
|
|
|
|
0, /* __DRI_ATTRIB_AUX_BUFFERS */
|
|
|
|
0, /* __DRI_ATTRIB_TRANSPARENT_TYPE */
|
|
|
|
0, /* __DRI_ATTRIB_TRANSPARENT_INDEX_VALUE */
|
|
|
|
0, /* __DRI_ATTRIB_TRANSPARENT_RED_VALUE */
|
|
|
|
0, /* __DRI_ATTRIB_TRANSPARENT_GREEN_VALUE */
|
|
|
|
0, /* __DRI_ATTRIB_TRANSPARENT_BLUE_VALUE */
|
|
|
|
0, /* __DRI_ATTRIB_TRANSPARENT_ALPHA_VALUE */
|
2013-07-17 12:49:21 +01:00
|
|
|
0, /* __DRI_ATTRIB_FLOAT_MODE (deprecated) */
|
2010-02-03 15:18:28 +00:00
|
|
|
0, /* __DRI_ATTRIB_RED_MASK */
|
|
|
|
0, /* __DRI_ATTRIB_GREEN_MASK */
|
|
|
|
0, /* __DRI_ATTRIB_BLUE_MASK */
|
|
|
|
0, /* __DRI_ATTRIB_ALPHA_MASK */
|
|
|
|
EGL_MAX_PBUFFER_WIDTH, /* __DRI_ATTRIB_MAX_PBUFFER_WIDTH */
|
|
|
|
EGL_MAX_PBUFFER_HEIGHT, /* __DRI_ATTRIB_MAX_PBUFFER_HEIGHT */
|
|
|
|
EGL_MAX_PBUFFER_PIXELS, /* __DRI_ATTRIB_MAX_PBUFFER_PIXELS */
|
|
|
|
0, /* __DRI_ATTRIB_OPTIMAL_PBUFFER_WIDTH */
|
|
|
|
0, /* __DRI_ATTRIB_OPTIMAL_PBUFFER_HEIGHT */
|
|
|
|
0, /* __DRI_ATTRIB_VISUAL_SELECT_GROUP */
|
|
|
|
0, /* __DRI_ATTRIB_SWAP_METHOD */
|
|
|
|
EGL_MAX_SWAP_INTERVAL, /* __DRI_ATTRIB_MAX_SWAP_INTERVAL */
|
|
|
|
EGL_MIN_SWAP_INTERVAL, /* __DRI_ATTRIB_MIN_SWAP_INTERVAL */
|
2010-02-05 02:49:44 +00:00
|
|
|
0, /* __DRI_ATTRIB_BIND_TO_TEXTURE_RGB */
|
|
|
|
0, /* __DRI_ATTRIB_BIND_TO_TEXTURE_RGBA */
|
2010-02-03 15:18:28 +00:00
|
|
|
0, /* __DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE */
|
|
|
|
0, /* __DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS */
|
2010-05-07 03:40:25 +01:00
|
|
|
EGL_Y_INVERTED_NOK, /* __DRI_ATTRIB_YINVERTED */
|
2011-03-06 23:29:13 +00:00
|
|
|
0, /* __DRI_ATTRIB_FRAMEBUFFER_SRGB_CAPABLE */
|
2010-02-03 15:18:28 +00:00
|
|
|
};
|
|
|
|
|
2011-06-11 22:00:40 +01:00
|
|
|
static EGLBoolean
|
|
|
|
dri2_match_config(const _EGLConfig *conf, const _EGLConfig *criteria)
|
|
|
|
{
|
|
|
|
if (_eglCompareConfigs(conf, criteria, NULL, EGL_FALSE) != 0)
|
|
|
|
return EGL_FALSE;
|
|
|
|
|
|
|
|
if (!_eglMatchConfig(conf, criteria))
|
|
|
|
return EGL_FALSE;
|
|
|
|
|
|
|
|
return EGL_TRUE;
|
|
|
|
}
|
|
|
|
|
2011-02-03 03:10:40 +00:00
|
|
|
struct dri2_egl_config *
|
2010-02-10 01:49:40 +00:00
|
|
|
dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id,
|
2013-09-15 07:13:22 +01:00
|
|
|
EGLint surface_type, const EGLint *attr_list,
|
2011-08-05 06:36:14 +01:00
|
|
|
const unsigned int *rgba_masks)
|
2010-02-03 15:18:28 +00:00
|
|
|
{
|
|
|
|
struct dri2_egl_config *conf;
|
|
|
|
struct dri2_egl_display *dri2_dpy;
|
2010-02-10 02:01:04 +00:00
|
|
|
_EGLConfig base;
|
2010-02-05 02:49:44 +00:00
|
|
|
unsigned int attrib, value, double_buffer;
|
|
|
|
EGLint key, bind_to_texture_rgb, bind_to_texture_rgba;
|
2011-08-05 06:36:14 +01:00
|
|
|
unsigned int dri_masks[4] = { 0, 0, 0, 0 };
|
2011-02-09 14:30:20 +00:00
|
|
|
_EGLConfig *matching_config;
|
|
|
|
EGLint num_configs = 0;
|
|
|
|
EGLint config_id;
|
2010-02-03 15:18:28 +00:00
|
|
|
int i;
|
|
|
|
|
|
|
|
dri2_dpy = disp->DriverData;
|
2010-02-10 02:01:04 +00:00
|
|
|
_eglInitConfig(&base, disp, id);
|
2010-02-03 15:18:28 +00:00
|
|
|
|
|
|
|
i = 0;
|
2010-07-27 23:25:54 +01:00
|
|
|
double_buffer = 0;
|
|
|
|
bind_to_texture_rgb = 0;
|
|
|
|
bind_to_texture_rgba = 0;
|
|
|
|
|
2010-02-03 15:18:28 +00:00
|
|
|
while (dri2_dpy->core->indexConfigAttrib(dri_config, i++, &attrib, &value)) {
|
|
|
|
switch (attrib) {
|
|
|
|
case __DRI_ATTRIB_RENDER_TYPE:
|
|
|
|
if (value & __DRI_ATTRIB_RGBA_BIT)
|
|
|
|
value = EGL_RGB_BUFFER;
|
|
|
|
else if (value & __DRI_ATTRIB_LUMINANCE_BIT)
|
|
|
|
value = EGL_LUMINANCE_BUFFER;
|
|
|
|
else
|
2013-07-18 23:13:45 +01:00
|
|
|
return NULL;
|
2010-02-10 02:01:04 +00:00
|
|
|
_eglSetConfigKey(&base, EGL_COLOR_BUFFER_TYPE, value);
|
2010-02-03 15:18:28 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case __DRI_ATTRIB_CONFIG_CAVEAT:
|
|
|
|
if (value & __DRI_ATTRIB_NON_CONFORMANT_CONFIG)
|
|
|
|
value = EGL_NON_CONFORMANT_CONFIG;
|
|
|
|
else if (value & __DRI_ATTRIB_SLOW_BIT)
|
|
|
|
value = EGL_SLOW_CONFIG;
|
|
|
|
else
|
|
|
|
value = EGL_NONE;
|
2010-02-10 02:01:04 +00:00
|
|
|
_eglSetConfigKey(&base, EGL_CONFIG_CAVEAT, value);
|
2010-02-03 15:18:28 +00:00
|
|
|
break;
|
|
|
|
|
2010-02-05 02:49:44 +00:00
|
|
|
case __DRI_ATTRIB_BIND_TO_TEXTURE_RGB:
|
|
|
|
bind_to_texture_rgb = value;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case __DRI_ATTRIB_BIND_TO_TEXTURE_RGBA:
|
|
|
|
bind_to_texture_rgba = value;
|
|
|
|
break;
|
|
|
|
|
2010-02-03 15:18:28 +00:00
|
|
|
case __DRI_ATTRIB_DOUBLE_BUFFER:
|
2010-02-05 02:49:44 +00:00
|
|
|
double_buffer = value;
|
2010-02-03 15:18:28 +00:00
|
|
|
break;
|
|
|
|
|
2011-08-05 06:36:14 +01:00
|
|
|
case __DRI_ATTRIB_RED_MASK:
|
|
|
|
dri_masks[0] = value;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case __DRI_ATTRIB_GREEN_MASK:
|
|
|
|
dri_masks[1] = value;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case __DRI_ATTRIB_BLUE_MASK:
|
|
|
|
dri_masks[2] = value;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case __DRI_ATTRIB_ALPHA_MASK:
|
|
|
|
dri_masks[3] = value;
|
|
|
|
break;
|
|
|
|
|
2010-02-03 15:18:28 +00:00
|
|
|
default:
|
|
|
|
key = dri2_to_egl_attribute_map[attrib];
|
|
|
|
if (key != 0)
|
2010-02-10 02:01:04 +00:00
|
|
|
_eglSetConfigKey(&base, key, value);
|
2010-02-03 15:18:28 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-09 14:30:20 +00:00
|
|
|
if (attr_list)
|
|
|
|
for (i = 0; attr_list[i] != EGL_NONE; i += 2)
|
|
|
|
_eglSetConfigKey(&base, attr_list[i], attr_list[i+1]);
|
2010-02-10 01:49:40 +00:00
|
|
|
|
2011-08-05 06:36:14 +01:00
|
|
|
if (rgba_masks && memcmp(rgba_masks, dri_masks, sizeof(dri_masks)))
|
|
|
|
return NULL;
|
|
|
|
|
2010-10-22 08:03:11 +01:00
|
|
|
base.NativeRenderable = EGL_TRUE;
|
2010-02-10 02:01:04 +00:00
|
|
|
|
2010-10-22 08:03:11 +01:00
|
|
|
base.SurfaceType = surface_type;
|
2011-02-04 11:32:30 +00:00
|
|
|
if (surface_type & (EGL_PBUFFER_BIT |
|
|
|
|
(disp->Extensions.NOK_texture_from_pixmap ? EGL_PIXMAP_BIT : 0))) {
|
2010-10-22 08:03:11 +01:00
|
|
|
base.BindToTextureRGB = bind_to_texture_rgb;
|
|
|
|
if (base.AlphaSize > 0)
|
|
|
|
base.BindToTextureRGBA = bind_to_texture_rgba;
|
2010-02-05 02:49:44 +00:00
|
|
|
}
|
2010-02-10 01:49:40 +00:00
|
|
|
|
2011-01-13 08:53:13 +00:00
|
|
|
base.RenderableType = disp->ClientAPIs;
|
|
|
|
base.Conformant = disp->ClientAPIs;
|
2010-02-03 15:18:28 +00:00
|
|
|
|
egl/dri2: Fix min/max swap interval of configs
The commit below exposed a bug in dri2_add_config.
commit 3998f8c6b5da1a223926249755e54d8f701f81ab
Author: Ralf Jung <post@ralfj.de>
Date: Tue Apr 9 14:09:50 2013 +0200
egl/x11: Fix initialisation of swap_interval
This little code snippet near the bottom of dri2_add_config,
if (double_buffer) {
...
conf->base.MinSwapInterval = dri2_dpy->min_swap_interval;
conf->base.MaxSwapInterval = dri2_dpy->max_swap_interval;
}
it never did what it claimed to do. The assignment never changed the value
of conf->base.MaxSwapInterval, because dri2_dpy->max_swap_interval was,
until the above exposing commit, unitialized here. That is,
conf->base.MaxSwapInterval was 0 before and after assignment. Ditto for
the min swap interval.
Above the troublesome code snippet, the call to _eglFilterArray rejects
the config as unmatching if its swap interval bounds differ from the base
config's. Before the exposing commit, at the call to _eglFilterArray, the
swap interval bounds were always [0,0], and hence no config was rejected
due to swap interval.
After the exposing commit, _eglFilterArray incorrectly rejected some
configs, which prevented dri2_egl_config::dri_double_config from getting
set for the rejected config, which resulted in a NULL pointer getting
passed into dri2CreateNewDrawable, and then segfault.
The solution: set the swap interval bounds before _eglFilterArray.
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=63447
Tested-by: Lu Hua <huax.lu@intel.com>
Signed-off-by: Chad Versace <chad.versace@linux.intel.com>
2013-04-23 03:17:48 +01:00
|
|
|
base.MinSwapInterval = dri2_dpy->min_swap_interval;
|
|
|
|
base.MaxSwapInterval = dri2_dpy->max_swap_interval;
|
|
|
|
|
2010-02-10 02:01:04 +00:00
|
|
|
if (!_eglValidateConfig(&base, EGL_FALSE)) {
|
2010-02-05 02:49:44 +00:00
|
|
|
_eglLog(_EGL_DEBUG, "DRI2: failed to validate config %d", id);
|
2010-07-27 23:25:54 +01:00
|
|
|
return NULL;
|
2010-02-03 15:18:28 +00:00
|
|
|
}
|
|
|
|
|
2011-02-09 14:30:20 +00:00
|
|
|
config_id = base.ConfigID;
|
|
|
|
base.ConfigID = EGL_DONT_CARE;
|
|
|
|
base.SurfaceType = EGL_DONT_CARE;
|
|
|
|
num_configs = _eglFilterArray(disp->Configs, (void **) &matching_config, 1,
|
2011-06-11 22:00:40 +01:00
|
|
|
(_EGLArrayForEach) dri2_match_config, &base);
|
2011-02-09 14:30:20 +00:00
|
|
|
|
|
|
|
if (num_configs == 1) {
|
|
|
|
conf = (struct dri2_egl_config *) matching_config;
|
|
|
|
|
|
|
|
if (double_buffer && !conf->dri_double_config)
|
|
|
|
conf->dri_double_config = dri_config;
|
|
|
|
else if (!double_buffer && !conf->dri_single_config)
|
|
|
|
conf->dri_single_config = dri_config;
|
|
|
|
else
|
2011-05-12 18:30:05 +01:00
|
|
|
/* a similar config type is already added (unlikely) => discard */
|
|
|
|
return NULL;
|
2011-02-09 14:30:20 +00:00
|
|
|
}
|
2011-05-12 15:23:48 +01:00
|
|
|
else if (num_configs == 0) {
|
2011-02-09 14:30:20 +00:00
|
|
|
conf = malloc(sizeof *conf);
|
|
|
|
if (conf == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
2010-02-10 02:01:04 +00:00
|
|
|
memcpy(&conf->base, &base, sizeof base);
|
2011-02-09 14:30:20 +00:00
|
|
|
if (double_buffer) {
|
|
|
|
conf->dri_double_config = dri_config;
|
|
|
|
conf->dri_single_config = NULL;
|
|
|
|
} else {
|
|
|
|
conf->dri_single_config = dri_config;
|
|
|
|
conf->dri_double_config = NULL;
|
|
|
|
}
|
|
|
|
conf->base.SurfaceType = 0;
|
|
|
|
conf->base.ConfigID = config_id;
|
|
|
|
|
2010-10-22 17:47:22 +01:00
|
|
|
_eglLinkConfig(&conf->base);
|
2010-02-10 02:01:04 +00:00
|
|
|
}
|
2011-05-12 15:23:48 +01:00
|
|
|
else {
|
|
|
|
assert(0);
|
|
|
|
return NULL;
|
|
|
|
}
|
2010-07-27 23:25:54 +01:00
|
|
|
|
2011-12-20 16:17:02 +00:00
|
|
|
if (double_buffer) {
|
2011-08-31 23:20:06 +01:00
|
|
|
surface_type &= ~EGL_PIXMAP_BIT;
|
2011-12-20 16:17:02 +00:00
|
|
|
}
|
|
|
|
|
2011-08-31 23:20:06 +01:00
|
|
|
conf->base.SurfaceType |= surface_type;
|
2011-02-09 14:30:20 +00:00
|
|
|
|
2010-07-27 23:25:54 +01:00
|
|
|
return conf;
|
2010-02-03 15:18:28 +00:00
|
|
|
}
|
|
|
|
|
2011-05-30 09:50:52 +01:00
|
|
|
__DRIimage *
|
2010-09-23 03:01:17 +01:00
|
|
|
dri2_lookup_egl_image(__DRIscreen *screen, void *image, void *data)
|
2010-02-12 00:28:26 +00:00
|
|
|
{
|
2010-09-23 03:01:17 +01:00
|
|
|
_EGLDisplay *disp = data;
|
2010-02-12 00:28:26 +00:00
|
|
|
struct dri2_egl_image *dri2_img;
|
|
|
|
_EGLImage *img;
|
|
|
|
|
2010-09-23 17:39:42 +01:00
|
|
|
(void) screen;
|
|
|
|
|
2010-02-12 00:28:26 +00:00
|
|
|
img = _eglLookupImage(image, disp);
|
|
|
|
if (img == NULL) {
|
|
|
|
_eglError(EGL_BAD_PARAMETER, "dri2_lookup_egl_image");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
dri2_img = dri2_egl_image(image);
|
|
|
|
|
|
|
|
return dri2_img->dri_image;
|
|
|
|
}
|
|
|
|
|
2011-02-03 03:10:40 +00:00
|
|
|
const __DRIimageLookupExtension image_lookup_extension = {
|
2010-06-03 03:48:06 +01:00
|
|
|
{ __DRI_IMAGE_LOOKUP, 1 },
|
|
|
|
dri2_lookup_egl_image
|
|
|
|
};
|
|
|
|
|
2010-02-03 15:18:28 +00:00
|
|
|
static const char dri_driver_path[] = DEFAULT_DRIVER_DIR;
|
|
|
|
|
2010-02-09 15:57:43 +00:00
|
|
|
struct dri2_extension_match {
|
|
|
|
const char *name;
|
|
|
|
int version;
|
|
|
|
int offset;
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct dri2_extension_match dri2_driver_extensions[] = {
|
|
|
|
{ __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) },
|
2012-07-18 21:17:50 +01:00
|
|
|
{ __DRI_DRI2, 2, offsetof(struct dri2_egl_display, dri2) },
|
2010-09-23 17:40:58 +01:00
|
|
|
{ NULL, 0, 0 }
|
2010-02-09 15:57:43 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static struct dri2_extension_match dri2_core_extensions[] = {
|
|
|
|
{ __DRI2_FLUSH, 1, offsetof(struct dri2_egl_display, flush) },
|
2010-02-09 20:49:28 +00:00
|
|
|
{ __DRI_TEX_BUFFER, 2, offsetof(struct dri2_egl_display, tex_buffer) },
|
2013-03-19 17:20:36 +00:00
|
|
|
{ __DRI_IMAGE, 1, offsetof(struct dri2_egl_display, image) },
|
2010-09-23 17:40:58 +01:00
|
|
|
{ NULL, 0, 0 }
|
2010-02-09 15:57:43 +00:00
|
|
|
};
|
|
|
|
|
2011-02-17 04:05:15 +00:00
|
|
|
static struct dri2_extension_match swrast_driver_extensions[] = {
|
|
|
|
{ __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) },
|
|
|
|
{ __DRI_SWRAST, 2, offsetof(struct dri2_egl_display, swrast) },
|
2012-07-19 19:08:02 +01:00
|
|
|
{ NULL, 0, 0 }
|
2011-02-17 04:05:15 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static struct dri2_extension_match swrast_core_extensions[] = {
|
|
|
|
{ __DRI_TEX_BUFFER, 2, offsetof(struct dri2_egl_display, tex_buffer) },
|
2012-07-19 19:08:02 +01:00
|
|
|
{ NULL, 0, 0 }
|
2011-02-17 04:05:15 +00:00
|
|
|
};
|
|
|
|
|
2010-02-09 15:57:43 +00:00
|
|
|
static EGLBoolean
|
|
|
|
dri2_bind_extensions(struct dri2_egl_display *dri2_dpy,
|
|
|
|
struct dri2_extension_match *matches,
|
|
|
|
const __DRIextension **extensions)
|
|
|
|
{
|
|
|
|
int i, j, ret = EGL_TRUE;
|
|
|
|
void *field;
|
|
|
|
|
|
|
|
for (i = 0; extensions[i]; i++) {
|
|
|
|
_eglLog(_EGL_DEBUG, "DRI2: found extension `%s'", extensions[i]->name);
|
|
|
|
for (j = 0; matches[j].name; j++) {
|
|
|
|
if (strcmp(extensions[i]->name, matches[j].name) == 0 &&
|
|
|
|
extensions[i]->version >= matches[j].version) {
|
|
|
|
field = ((char *) dri2_dpy + matches[j].offset);
|
|
|
|
*(const __DRIextension **) field = extensions[i];
|
|
|
|
_eglLog(_EGL_INFO, "DRI2: found extension %s version %d",
|
|
|
|
extensions[i]->name, extensions[i]->version);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (j = 0; matches[j].name; j++) {
|
|
|
|
field = ((char *) dri2_dpy + matches[j].offset);
|
|
|
|
if (*(const __DRIextension **) field == NULL) {
|
|
|
|
_eglLog(_EGL_FATAL, "DRI2: did not find extension %s version %d",
|
|
|
|
matches[j].name, matches[j].version);
|
|
|
|
ret = EGL_FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-06-08 09:33:55 +01:00
|
|
|
static const __DRIextension **
|
|
|
|
dri2_open_driver(_EGLDisplay *disp)
|
2010-03-02 20:34:18 +00:00
|
|
|
{
|
2010-05-28 21:16:12 +01:00
|
|
|
struct dri2_egl_display *dri2_dpy = disp->DriverData;
|
2013-09-24 19:05:22 +01:00
|
|
|
const __DRIextension **extensions = NULL;
|
2010-03-02 20:34:18 +00:00
|
|
|
char path[PATH_MAX], *search_paths, *p, *next, *end;
|
2013-09-24 19:05:22 +01:00
|
|
|
char *get_extensions_name;
|
|
|
|
const __DRIextension **(*get_extensions)(void);
|
2010-02-03 15:18:28 +00:00
|
|
|
|
|
|
|
search_paths = NULL;
|
|
|
|
if (geteuid() == getuid()) {
|
|
|
|
/* don't allow setuid apps to use LIBGL_DRIVERS_PATH */
|
|
|
|
search_paths = getenv("LIBGL_DRIVERS_PATH");
|
|
|
|
}
|
|
|
|
if (search_paths == NULL)
|
|
|
|
search_paths = DEFAULT_DRIVER_DIR;
|
|
|
|
|
|
|
|
dri2_dpy->driver = NULL;
|
|
|
|
end = search_paths + strlen(search_paths);
|
|
|
|
for (p = search_paths; p < end && dri2_dpy->driver == NULL; p = next + 1) {
|
2010-05-20 22:44:43 +01:00
|
|
|
int len;
|
2010-02-03 15:18:28 +00:00
|
|
|
next = strchr(p, ':');
|
|
|
|
if (next == NULL)
|
|
|
|
next = end;
|
|
|
|
|
2010-05-20 22:44:43 +01:00
|
|
|
len = next - p;
|
|
|
|
#if GLX_USE_TLS
|
2010-02-03 15:18:28 +00:00
|
|
|
snprintf(path, sizeof path,
|
2010-05-20 22:44:43 +01:00
|
|
|
"%.*s/tls/%s_dri.so", len, p, dri2_dpy->driver_name);
|
2010-02-03 15:18:28 +00:00
|
|
|
dri2_dpy->driver = dlopen(path, RTLD_NOW | RTLD_GLOBAL);
|
2010-05-20 22:44:43 +01:00
|
|
|
#endif
|
|
|
|
if (dri2_dpy->driver == NULL) {
|
|
|
|
snprintf(path, sizeof path,
|
|
|
|
"%.*s/%s_dri.so", len, p, dri2_dpy->driver_name);
|
|
|
|
dri2_dpy->driver = dlopen(path, RTLD_NOW | RTLD_GLOBAL);
|
|
|
|
if (dri2_dpy->driver == NULL)
|
|
|
|
_eglLog(_EGL_DEBUG, "failed to open %s: %s\n", path, dlerror());
|
|
|
|
}
|
2013-12-19 05:11:00 +00:00
|
|
|
/* not need continue to loop all paths once the driver is found */
|
|
|
|
if (dri2_dpy->driver != NULL)
|
|
|
|
break;
|
2010-02-03 15:18:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (dri2_dpy->driver == NULL) {
|
2010-05-13 20:42:51 +01:00
|
|
|
_eglLog(_EGL_WARNING,
|
2011-06-08 09:33:55 +01:00
|
|
|
"DRI2: failed to open %s (search paths %s)",
|
|
|
|
dri2_dpy->driver_name, search_paths);
|
|
|
|
return NULL;
|
2010-02-03 15:18:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
_eglLog(_EGL_DEBUG, "DRI2: dlopen(%s)", path);
|
2013-09-24 19:05:22 +01:00
|
|
|
|
|
|
|
if (asprintf(&get_extensions_name, "%s_%s",
|
|
|
|
__DRI_DRIVER_GET_EXTENSIONS, dri2_dpy->driver_name) != -1) {
|
|
|
|
get_extensions = dlsym(dri2_dpy->driver, get_extensions_name);
|
|
|
|
if (get_extensions) {
|
|
|
|
extensions = get_extensions();
|
|
|
|
} else {
|
|
|
|
_eglLog(_EGL_DEBUG, "driver does not expose %s(): %s\n",
|
|
|
|
get_extensions_name, dlerror());
|
|
|
|
}
|
|
|
|
free(get_extensions_name);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!extensions)
|
|
|
|
extensions = dlsym(dri2_dpy->driver, __DRI_DRIVER_EXTENSIONS);
|
2010-02-03 15:18:28 +00:00
|
|
|
if (extensions == NULL) {
|
2010-05-13 20:42:51 +01:00
|
|
|
_eglLog(_EGL_WARNING,
|
2010-02-03 15:18:28 +00:00
|
|
|
"DRI2: driver exports no extensions (%s)", dlerror());
|
2010-05-28 21:16:12 +01:00
|
|
|
dlclose(dri2_dpy->driver);
|
2011-06-08 09:33:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return extensions;
|
|
|
|
}
|
|
|
|
|
|
|
|
EGLBoolean
|
|
|
|
dri2_load_driver(_EGLDisplay *disp)
|
|
|
|
{
|
|
|
|
struct dri2_egl_display *dri2_dpy = disp->DriverData;
|
|
|
|
const __DRIextension **extensions;
|
|
|
|
|
|
|
|
extensions = dri2_open_driver(disp);
|
|
|
|
if (!extensions)
|
|
|
|
return EGL_FALSE;
|
|
|
|
|
|
|
|
if (!dri2_bind_extensions(dri2_dpy, dri2_driver_extensions, extensions)) {
|
|
|
|
dlclose(dri2_dpy->driver);
|
2010-05-28 21:16:12 +01:00
|
|
|
return EGL_FALSE;
|
2010-02-03 15:18:28 +00:00
|
|
|
}
|
2013-09-27 19:39:25 +01:00
|
|
|
dri2_dpy->driver_extensions = extensions;
|
2010-02-03 15:18:28 +00:00
|
|
|
|
2011-06-08 09:33:55 +01:00
|
|
|
return EGL_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
EGLBoolean
|
|
|
|
dri2_load_driver_swrast(_EGLDisplay *disp)
|
|
|
|
{
|
|
|
|
struct dri2_egl_display *dri2_dpy = disp->DriverData;
|
|
|
|
const __DRIextension **extensions;
|
|
|
|
|
|
|
|
dri2_dpy->driver_name = "swrast";
|
|
|
|
extensions = dri2_open_driver(disp);
|
2011-06-08 09:33:56 +01:00
|
|
|
|
2011-06-08 09:33:55 +01:00
|
|
|
if (!extensions)
|
|
|
|
return EGL_FALSE;
|
|
|
|
|
|
|
|
if (!dri2_bind_extensions(dri2_dpy, swrast_driver_extensions, extensions)) {
|
|
|
|
dlclose(dri2_dpy->driver);
|
|
|
|
return EGL_FALSE;
|
|
|
|
}
|
2013-09-27 19:39:25 +01:00
|
|
|
dri2_dpy->driver_extensions = extensions;
|
2010-05-28 21:16:12 +01:00
|
|
|
|
|
|
|
return EGL_TRUE;
|
|
|
|
}
|
|
|
|
|
2011-05-30 09:50:52 +01:00
|
|
|
void
|
|
|
|
dri2_setup_screen(_EGLDisplay *disp)
|
2010-05-28 21:16:12 +01:00
|
|
|
{
|
2011-05-30 09:50:52 +01:00
|
|
|
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
2010-05-28 21:16:12 +01:00
|
|
|
unsigned int api_mask;
|
|
|
|
|
2011-02-17 04:05:15 +00:00
|
|
|
if (dri2_dpy->dri2) {
|
2012-07-18 21:17:50 +01:00
|
|
|
api_mask = dri2_dpy->dri2->getAPIMask(dri2_dpy->dri_screen);
|
2011-02-17 04:05:15 +00:00
|
|
|
} else {
|
|
|
|
assert(dri2_dpy->swrast);
|
egl/dri2: Add plumbing for EGL_OPENGL_ES3_BIT_KHR
Fixes error EGL_BAD_ATTRIBUTE in the tests below on Intel Sandybridge:
* piglit egl-create-context-verify-gl-flavor, testcase OpenGL ES 3.0
* gles3conform, revision 19700, when runnning GL3Tests with -fbo
This plumbing is added in order to comply with the EGL_KHR_create_context
spec. According to the EGL_KHR_create_context spec, it is illegal to call
eglCreateContext(EGL_CONTEXT_MAJOR_VERSION_KHR=3) with a config whose
EGL_RENDERABLE_TYPE does not contain the EGL_OPENGL_ES3_BIT_KHR. The
pertinent
portion of the spec is quoted below; the key word is "respectively".
* If <config> is not a valid EGLConfig, or does not support the
requested client API, then an EGL_BAD_CONFIG error is generated
(this includes requesting creation of an OpenGL ES 1.x, 2.0, or
3.0 context when the EGL_RENDERABLE_TYPE attribute of <config>
does not contain EGL_OPENGL_ES_BIT, EGL_OPENGL_ES2_BIT, or
EGL_OPENGL_ES3_BIT_KHR respectively).
To create this patch, I searched for all the ES2 bit plumbing by calling
`git grep "ES2_BIT\|DRI_API_GLES2" src/egl`, and then at each location
added a case for ES3.
Signed-off-by: Chad Versace <chad.versace@linux.intel.com>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
2012-11-20 21:43:11 +00:00
|
|
|
api_mask = 1 << __DRI_API_OPENGL |
|
|
|
|
1 << __DRI_API_GLES |
|
|
|
|
1 << __DRI_API_GLES2 |
|
|
|
|
1 << __DRI_API_GLES3;
|
2011-02-17 04:05:15 +00:00
|
|
|
}
|
2010-06-03 03:48:06 +01:00
|
|
|
|
2011-01-13 08:53:13 +00:00
|
|
|
disp->ClientAPIs = 0;
|
2010-06-03 03:48:06 +01:00
|
|
|
if (api_mask & (1 <<__DRI_API_OPENGL))
|
2011-01-13 08:53:13 +00:00
|
|
|
disp->ClientAPIs |= EGL_OPENGL_BIT;
|
2010-06-03 03:48:06 +01:00
|
|
|
if (api_mask & (1 <<__DRI_API_GLES))
|
2011-01-13 08:53:13 +00:00
|
|
|
disp->ClientAPIs |= EGL_OPENGL_ES_BIT;
|
2010-06-03 03:48:06 +01:00
|
|
|
if (api_mask & (1 << __DRI_API_GLES2))
|
2011-01-13 08:53:13 +00:00
|
|
|
disp->ClientAPIs |= EGL_OPENGL_ES2_BIT;
|
egl/dri2: Add plumbing for EGL_OPENGL_ES3_BIT_KHR
Fixes error EGL_BAD_ATTRIBUTE in the tests below on Intel Sandybridge:
* piglit egl-create-context-verify-gl-flavor, testcase OpenGL ES 3.0
* gles3conform, revision 19700, when runnning GL3Tests with -fbo
This plumbing is added in order to comply with the EGL_KHR_create_context
spec. According to the EGL_KHR_create_context spec, it is illegal to call
eglCreateContext(EGL_CONTEXT_MAJOR_VERSION_KHR=3) with a config whose
EGL_RENDERABLE_TYPE does not contain the EGL_OPENGL_ES3_BIT_KHR. The
pertinent
portion of the spec is quoted below; the key word is "respectively".
* If <config> is not a valid EGLConfig, or does not support the
requested client API, then an EGL_BAD_CONFIG error is generated
(this includes requesting creation of an OpenGL ES 1.x, 2.0, or
3.0 context when the EGL_RENDERABLE_TYPE attribute of <config>
does not contain EGL_OPENGL_ES_BIT, EGL_OPENGL_ES2_BIT, or
EGL_OPENGL_ES3_BIT_KHR respectively).
To create this patch, I searched for all the ES2 bit plumbing by calling
`git grep "ES2_BIT\|DRI_API_GLES2" src/egl`, and then at each location
added a case for ES3.
Signed-off-by: Chad Versace <chad.versace@linux.intel.com>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
2012-11-20 21:43:11 +00:00
|
|
|
if (api_mask & (1 << __DRI_API_GLES3))
|
|
|
|
disp->ClientAPIs |= EGL_OPENGL_ES3_BIT_KHR;
|
2010-06-03 03:48:06 +01:00
|
|
|
|
2012-07-18 21:17:50 +01:00
|
|
|
assert(dri2_dpy->dri2 || dri2_dpy->swrast);
|
|
|
|
disp->Extensions.KHR_surfaceless_context = EGL_TRUE;
|
2014-03-07 18:05:47 +00:00
|
|
|
disp->Extensions.MESA_configless_context = EGL_TRUE;
|
2010-07-27 23:25:54 +01:00
|
|
|
|
2012-08-17 18:08:10 +01:00
|
|
|
if (dri2_dpy->dri2 && dri2_dpy->dri2->base.version >= 3) {
|
2012-07-20 00:04:01 +01:00
|
|
|
disp->Extensions.KHR_create_context = EGL_TRUE;
|
|
|
|
|
|
|
|
if (dri2_dpy->robustness)
|
|
|
|
disp->Extensions.EXT_create_context_robustness = EGL_TRUE;
|
|
|
|
}
|
|
|
|
|
2011-03-08 01:18:29 +00:00
|
|
|
if (dri2_dpy->image) {
|
|
|
|
disp->Extensions.MESA_drm_image = EGL_TRUE;
|
|
|
|
disp->Extensions.KHR_image_base = EGL_TRUE;
|
|
|
|
disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE;
|
2012-11-27 13:19:54 +00:00
|
|
|
if (dri2_dpy->image->base.version >= 5 &&
|
|
|
|
dri2_dpy->image->createImageFromTexture) {
|
|
|
|
disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE;
|
|
|
|
disp->Extensions.KHR_gl_texture_cubemap_image = EGL_TRUE;
|
|
|
|
}
|
2013-11-10 18:32:01 +00:00
|
|
|
#ifdef HAVE_DRM_PLATFORM
|
2013-03-22 13:58:05 +00:00
|
|
|
if (dri2_dpy->image->base.version >= 8 &&
|
|
|
|
dri2_dpy->image->createImageFromDmaBufs) {
|
|
|
|
disp->Extensions.EXT_image_dma_buf_import = EGL_TRUE;
|
|
|
|
}
|
2013-11-10 18:32:01 +00:00
|
|
|
#endif
|
2011-03-08 01:18:29 +00:00
|
|
|
}
|
2011-05-30 09:50:52 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
EGLBoolean
|
|
|
|
dri2_create_screen(_EGLDisplay *disp)
|
|
|
|
{
|
|
|
|
const __DRIextension **extensions;
|
|
|
|
struct dri2_egl_display *dri2_dpy;
|
|
|
|
|
|
|
|
dri2_dpy = disp->DriverData;
|
|
|
|
|
|
|
|
if (dri2_dpy->dri2) {
|
2013-09-27 19:39:25 +01:00
|
|
|
if (dri2_dpy->dri2->base.version >= 4) {
|
|
|
|
dri2_dpy->dri_screen =
|
|
|
|
dri2_dpy->dri2->createNewScreen2(0, dri2_dpy->fd,
|
|
|
|
dri2_dpy->extensions,
|
|
|
|
dri2_dpy->driver_extensions,
|
|
|
|
&dri2_dpy->driver_configs, disp);
|
|
|
|
} else {
|
|
|
|
dri2_dpy->dri_screen =
|
|
|
|
dri2_dpy->dri2->createNewScreen(0, dri2_dpy->fd,
|
|
|
|
dri2_dpy->extensions,
|
|
|
|
&dri2_dpy->driver_configs, disp);
|
|
|
|
}
|
2011-05-30 09:50:52 +01:00
|
|
|
} else {
|
|
|
|
assert(dri2_dpy->swrast);
|
2013-09-27 19:39:25 +01:00
|
|
|
if (dri2_dpy->swrast->base.version >= 4) {
|
|
|
|
dri2_dpy->dri_screen =
|
|
|
|
dri2_dpy->swrast->createNewScreen2(0, dri2_dpy->extensions,
|
|
|
|
dri2_dpy->driver_extensions,
|
|
|
|
&dri2_dpy->driver_configs, disp);
|
|
|
|
} else {
|
|
|
|
dri2_dpy->dri_screen =
|
|
|
|
dri2_dpy->swrast->createNewScreen(0, dri2_dpy->extensions,
|
|
|
|
&dri2_dpy->driver_configs, disp);
|
|
|
|
}
|
2011-05-30 09:50:52 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (dri2_dpy->dri_screen == NULL) {
|
|
|
|
_eglLog(_EGL_WARNING, "DRI2: failed to create dri screen");
|
|
|
|
return EGL_FALSE;
|
|
|
|
}
|
|
|
|
|
2011-06-27 09:23:34 +01:00
|
|
|
dri2_dpy->own_dri_screen = 1;
|
|
|
|
|
2011-05-30 09:50:52 +01:00
|
|
|
extensions = dri2_dpy->core->getExtensions(dri2_dpy->dri_screen);
|
|
|
|
|
|
|
|
if (dri2_dpy->dri2) {
|
2012-07-20 00:04:01 +01:00
|
|
|
unsigned i;
|
|
|
|
|
2011-05-30 09:50:52 +01:00
|
|
|
if (!dri2_bind_extensions(dri2_dpy, dri2_core_extensions, extensions))
|
|
|
|
goto cleanup_dri_screen;
|
2012-07-20 00:04:01 +01:00
|
|
|
|
|
|
|
for (i = 0; extensions[i]; i++) {
|
|
|
|
if (strcmp(extensions[i]->name, __DRI2_ROBUSTNESS) == 0) {
|
|
|
|
dri2_dpy->robustness = (__DRIrobustnessExtension *) extensions[i];
|
|
|
|
}
|
2012-09-25 22:05:30 +01:00
|
|
|
if (strcmp(extensions[i]->name, __DRI2_CONFIG_QUERY) == 0) {
|
|
|
|
dri2_dpy->config = (__DRI2configQueryExtension *) extensions[i];
|
|
|
|
}
|
2012-07-20 00:04:01 +01:00
|
|
|
}
|
2011-05-30 09:50:52 +01:00
|
|
|
} else {
|
|
|
|
assert(dri2_dpy->swrast);
|
|
|
|
if (!dri2_bind_extensions(dri2_dpy, swrast_core_extensions, extensions))
|
|
|
|
goto cleanup_dri_screen;
|
|
|
|
}
|
|
|
|
|
|
|
|
dri2_setup_screen(disp);
|
2011-03-08 01:18:29 +00:00
|
|
|
|
2010-06-03 03:48:06 +01:00
|
|
|
return EGL_TRUE;
|
|
|
|
|
|
|
|
cleanup_dri_screen:
|
|
|
|
dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
|
|
|
|
|
|
|
|
return EGL_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Called via eglInitialize(), GLX_drv->API.Initialize().
|
|
|
|
*/
|
|
|
|
static EGLBoolean
|
2011-01-13 08:53:13 +00:00
|
|
|
dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp)
|
2010-06-03 03:48:06 +01:00
|
|
|
{
|
2011-01-12 20:40:38 +00:00
|
|
|
/* not until swrast_dri is supported */
|
|
|
|
if (disp->Options.UseFallback)
|
|
|
|
return EGL_FALSE;
|
|
|
|
|
2010-06-03 03:48:06 +01:00
|
|
|
switch (disp->Platform) {
|
2011-05-11 18:58:37 +01:00
|
|
|
#ifdef HAVE_X11_PLATFORM
|
2010-06-03 03:48:06 +01:00
|
|
|
case _EGL_PLATFORM_X11:
|
2011-01-12 16:27:45 +00:00
|
|
|
if (disp->Options.TestOnly)
|
|
|
|
return EGL_TRUE;
|
2011-01-13 08:53:13 +00:00
|
|
|
return dri2_initialize_x11(drv, disp);
|
2011-05-11 18:58:37 +01:00
|
|
|
#endif
|
2010-06-03 03:48:06 +01:00
|
|
|
|
2011-06-24 20:45:05 +01:00
|
|
|
#ifdef HAVE_DRM_PLATFORM
|
2010-06-03 03:48:06 +01:00
|
|
|
case _EGL_PLATFORM_DRM:
|
2011-01-12 16:27:45 +00:00
|
|
|
if (disp->Options.TestOnly)
|
|
|
|
return EGL_TRUE;
|
2011-01-13 08:53:13 +00:00
|
|
|
return dri2_initialize_drm(drv, disp);
|
2011-06-24 20:45:05 +01:00
|
|
|
#endif
|
2011-02-04 11:39:40 +00:00
|
|
|
#ifdef HAVE_WAYLAND_PLATFORM
|
|
|
|
case _EGL_PLATFORM_WAYLAND:
|
|
|
|
if (disp->Options.TestOnly)
|
|
|
|
return EGL_TRUE;
|
|
|
|
return dri2_initialize_wayland(drv, disp);
|
|
|
|
#endif
|
2011-08-05 06:39:18 +01:00
|
|
|
#ifdef HAVE_ANDROID_PLATFORM
|
|
|
|
case _EGL_PLATFORM_ANDROID:
|
|
|
|
if (disp->Options.TestOnly)
|
|
|
|
return EGL_TRUE;
|
|
|
|
return dri2_initialize_android(drv, disp);
|
2010-06-03 03:48:06 +01:00
|
|
|
#endif
|
|
|
|
|
|
|
|
default:
|
|
|
|
return EGL_FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-02-03 15:18:28 +00:00
|
|
|
/**
|
|
|
|
* Called via eglTerminate(), drv->API.Terminate().
|
|
|
|
*/
|
|
|
|
static EGLBoolean
|
|
|
|
dri2_terminate(_EGLDriver *drv, _EGLDisplay *disp)
|
|
|
|
{
|
|
|
|
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
|
|
|
|
|
|
|
_eglReleaseDisplayResources(drv, disp);
|
|
|
|
_eglCleanupDisplay(disp);
|
|
|
|
|
2011-06-27 09:23:34 +01:00
|
|
|
if (dri2_dpy->own_dri_screen)
|
|
|
|
dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
|
2011-02-17 04:05:15 +00:00
|
|
|
if (dri2_dpy->fd)
|
|
|
|
close(dri2_dpy->fd);
|
2011-06-27 09:23:34 +01:00
|
|
|
if (dri2_dpy->driver)
|
|
|
|
dlclose(dri2_dpy->driver);
|
2012-09-04 04:24:35 +01:00
|
|
|
free(dri2_dpy->device_name);
|
2011-06-11 21:07:02 +01:00
|
|
|
|
2014-01-29 02:53:56 +00:00
|
|
|
switch (disp->Platform) {
|
2011-05-11 18:58:37 +01:00
|
|
|
#ifdef HAVE_X11_PLATFORM
|
2014-01-29 02:53:56 +00:00
|
|
|
case _EGL_PLATFORM_X11:
|
|
|
|
if (dri2_dpy->own_device) {
|
2011-06-11 21:07:02 +01:00
|
|
|
xcb_disconnect(dri2_dpy->conn);
|
2014-01-29 02:53:56 +00:00
|
|
|
}
|
|
|
|
break;
|
2011-06-11 21:07:02 +01:00
|
|
|
#endif
|
2011-06-29 07:49:39 +01:00
|
|
|
#ifdef HAVE_DRM_PLATFORM
|
2014-01-29 02:53:56 +00:00
|
|
|
case _EGL_PLATFORM_DRM:
|
|
|
|
if (dri2_dpy->own_device) {
|
|
|
|
gbm_device_destroy(&dri2_dpy->gbm_dri->base.base);
|
|
|
|
}
|
|
|
|
break;
|
2011-05-11 18:58:37 +01:00
|
|
|
#endif
|
2014-01-29 02:53:56 +00:00
|
|
|
#ifdef HAVE_WAYLAND_PLATFORM
|
|
|
|
case _EGL_PLATFORM_WAYLAND:
|
|
|
|
wl_drm_destroy(dri2_dpy->wl_drm);
|
|
|
|
if (dri2_dpy->own_device) {
|
|
|
|
wl_display_disconnect(dri2_dpy->wl_dpy);
|
2011-06-11 21:07:02 +01:00
|
|
|
}
|
2014-01-29 02:53:56 +00:00
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
default:
|
|
|
|
break;
|
2011-06-11 21:07:02 +01:00
|
|
|
}
|
|
|
|
|
2010-02-03 15:18:28 +00:00
|
|
|
free(dri2_dpy);
|
|
|
|
disp->DriverData = NULL;
|
|
|
|
|
|
|
|
return EGL_TRUE;
|
|
|
|
}
|
|
|
|
|
2012-11-09 22:06:41 +00:00
|
|
|
/**
|
|
|
|
* Set the error code after a call to
|
|
|
|
* dri2_egl_display::dri2::createContextAttribs.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
dri2_create_context_attribs_error(int dri_error)
|
|
|
|
{
|
|
|
|
EGLint egl_error;
|
|
|
|
|
|
|
|
switch (dri_error) {
|
|
|
|
case __DRI_CTX_ERROR_SUCCESS:
|
|
|
|
return;
|
|
|
|
|
|
|
|
case __DRI_CTX_ERROR_NO_MEMORY:
|
|
|
|
egl_error = EGL_BAD_ALLOC;
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* From the EGL_KHR_create_context spec, section "Errors":
|
|
|
|
*
|
|
|
|
* * If <config> does not support a client API context compatible
|
|
|
|
* with the requested API major and minor version, [...] context flags,
|
|
|
|
* and context reset notification behavior (for client API types where
|
|
|
|
* these attributes are supported), then an EGL_BAD_MATCH error is
|
|
|
|
* generated.
|
|
|
|
*
|
|
|
|
* * If an OpenGL ES context is requested and the values for
|
|
|
|
* attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
|
|
|
|
* EGL_CONTEXT_MINOR_VERSION_KHR specify an OpenGL ES version that
|
|
|
|
* is not defined, than an EGL_BAD_MATCH error is generated.
|
|
|
|
*
|
|
|
|
* * If an OpenGL context is requested, the requested version is
|
|
|
|
* greater than 3.2, and the value for attribute
|
|
|
|
* EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR has no bits set; has any
|
|
|
|
* bits set other than EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR and
|
|
|
|
* EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; has more than
|
|
|
|
* one of these bits set; or if the implementation does not support
|
|
|
|
* the requested profile, then an EGL_BAD_MATCH error is generated.
|
|
|
|
*/
|
|
|
|
case __DRI_CTX_ERROR_BAD_API:
|
|
|
|
case __DRI_CTX_ERROR_BAD_VERSION:
|
|
|
|
case __DRI_CTX_ERROR_BAD_FLAG:
|
|
|
|
egl_error = EGL_BAD_MATCH;
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* From the EGL_KHR_create_context spec, section "Errors":
|
|
|
|
*
|
|
|
|
* * If an attribute name or attribute value in <attrib_list> is not
|
|
|
|
* recognized (including unrecognized bits in bitmask attributes),
|
|
|
|
* then an EGL_BAD_ATTRIBUTE error is generated."
|
|
|
|
*/
|
|
|
|
case __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE:
|
|
|
|
case __DRI_CTX_ERROR_UNKNOWN_FLAG:
|
|
|
|
egl_error = EGL_BAD_ATTRIBUTE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
assert(0);
|
|
|
|
egl_error = EGL_BAD_MATCH;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
_eglError(egl_error, "dri2_create_context");
|
|
|
|
}
|
2010-02-03 15:18:28 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Called via eglCreateContext(), drv->API.CreateContext().
|
|
|
|
*/
|
|
|
|
static _EGLContext *
|
|
|
|
dri2_create_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
|
|
|
|
_EGLContext *share_list, const EGLint *attrib_list)
|
|
|
|
{
|
|
|
|
struct dri2_egl_context *dri2_ctx;
|
|
|
|
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
|
|
|
struct dri2_egl_context *dri2_ctx_shared = dri2_egl_context(share_list);
|
2012-07-18 22:37:28 +01:00
|
|
|
__DRIcontext *shared =
|
|
|
|
dri2_ctx_shared ? dri2_ctx_shared->dri_context : NULL;
|
2010-02-03 15:18:28 +00:00
|
|
|
struct dri2_egl_config *dri2_config = dri2_egl_config(conf);
|
2010-07-27 23:25:54 +01:00
|
|
|
const __DRIconfig *dri_config;
|
2010-04-27 16:38:46 +01:00
|
|
|
int api;
|
2010-02-03 15:18:28 +00:00
|
|
|
|
2010-09-23 17:39:42 +01:00
|
|
|
(void) drv;
|
|
|
|
|
2010-02-03 15:18:28 +00:00
|
|
|
dri2_ctx = malloc(sizeof *dri2_ctx);
|
|
|
|
if (!dri2_ctx) {
|
|
|
|
_eglError(EGL_BAD_ALLOC, "eglCreateContext");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-02-05 15:49:33 +00:00
|
|
|
if (!_eglInitContext(&dri2_ctx->base, disp, conf, attrib_list))
|
|
|
|
goto cleanup;
|
2010-02-03 15:18:28 +00:00
|
|
|
|
2010-04-27 16:38:46 +01:00
|
|
|
switch (dri2_ctx->base.ClientAPI) {
|
|
|
|
case EGL_OPENGL_ES_API:
|
2012-07-18 23:59:15 +01:00
|
|
|
switch (dri2_ctx->base.ClientMajorVersion) {
|
2010-04-27 16:38:46 +01:00
|
|
|
case 1:
|
|
|
|
api = __DRI_API_GLES;
|
|
|
|
break;
|
|
|
|
case 2:
|
2013-01-15 22:17:46 +00:00
|
|
|
api = __DRI_API_GLES2;
|
egl/dri2: Add plumbing for EGL_OPENGL_ES3_BIT_KHR
Fixes error EGL_BAD_ATTRIBUTE in the tests below on Intel Sandybridge:
* piglit egl-create-context-verify-gl-flavor, testcase OpenGL ES 3.0
* gles3conform, revision 19700, when runnning GL3Tests with -fbo
This plumbing is added in order to comply with the EGL_KHR_create_context
spec. According to the EGL_KHR_create_context spec, it is illegal to call
eglCreateContext(EGL_CONTEXT_MAJOR_VERSION_KHR=3) with a config whose
EGL_RENDERABLE_TYPE does not contain the EGL_OPENGL_ES3_BIT_KHR. The
pertinent
portion of the spec is quoted below; the key word is "respectively".
* If <config> is not a valid EGLConfig, or does not support the
requested client API, then an EGL_BAD_CONFIG error is generated
(this includes requesting creation of an OpenGL ES 1.x, 2.0, or
3.0 context when the EGL_RENDERABLE_TYPE attribute of <config>
does not contain EGL_OPENGL_ES_BIT, EGL_OPENGL_ES2_BIT, or
EGL_OPENGL_ES3_BIT_KHR respectively).
To create this patch, I searched for all the ES2 bit plumbing by calling
`git grep "ES2_BIT\|DRI_API_GLES2" src/egl`, and then at each location
added a case for ES3.
Signed-off-by: Chad Versace <chad.versace@linux.intel.com>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
2012-11-20 21:43:11 +00:00
|
|
|
break;
|
2012-07-20 00:12:13 +01:00
|
|
|
case 3:
|
egl/dri2: Add plumbing for EGL_OPENGL_ES3_BIT_KHR
Fixes error EGL_BAD_ATTRIBUTE in the tests below on Intel Sandybridge:
* piglit egl-create-context-verify-gl-flavor, testcase OpenGL ES 3.0
* gles3conform, revision 19700, when runnning GL3Tests with -fbo
This plumbing is added in order to comply with the EGL_KHR_create_context
spec. According to the EGL_KHR_create_context spec, it is illegal to call
eglCreateContext(EGL_CONTEXT_MAJOR_VERSION_KHR=3) with a config whose
EGL_RENDERABLE_TYPE does not contain the EGL_OPENGL_ES3_BIT_KHR. The
pertinent
portion of the spec is quoted below; the key word is "respectively".
* If <config> is not a valid EGLConfig, or does not support the
requested client API, then an EGL_BAD_CONFIG error is generated
(this includes requesting creation of an OpenGL ES 1.x, 2.0, or
3.0 context when the EGL_RENDERABLE_TYPE attribute of <config>
does not contain EGL_OPENGL_ES_BIT, EGL_OPENGL_ES2_BIT, or
EGL_OPENGL_ES3_BIT_KHR respectively).
To create this patch, I searched for all the ES2 bit plumbing by calling
`git grep "ES2_BIT\|DRI_API_GLES2" src/egl`, and then at each location
added a case for ES3.
Signed-off-by: Chad Versace <chad.versace@linux.intel.com>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
2012-11-20 21:43:11 +00:00
|
|
|
api = __DRI_API_GLES3;
|
2010-04-27 16:38:46 +01:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
_eglError(EGL_BAD_PARAMETER, "eglCreateContext");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case EGL_OPENGL_API:
|
2012-07-20 00:04:01 +01:00
|
|
|
if ((dri2_ctx->base.ClientMajorVersion >= 4
|
|
|
|
|| (dri2_ctx->base.ClientMajorVersion == 3
|
|
|
|
&& dri2_ctx->base.ClientMinorVersion >= 2))
|
|
|
|
&& dri2_ctx->base.Profile == EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR)
|
|
|
|
api = __DRI_API_OPENGL_CORE;
|
|
|
|
else
|
|
|
|
api = __DRI_API_OPENGL;
|
2010-04-27 16:38:46 +01:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
_eglError(EGL_BAD_PARAMETER, "eglCreateContext");
|
2013-02-01 07:41:14 +00:00
|
|
|
free(dri2_ctx);
|
2010-04-27 16:38:46 +01:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2011-02-09 14:30:20 +00:00
|
|
|
if (conf != NULL) {
|
|
|
|
/* The config chosen here isn't necessarily
|
|
|
|
* used for surfaces later.
|
|
|
|
* A pixmap surface will use the single config.
|
|
|
|
* This opportunity depends on disabling the
|
|
|
|
* doubleBufferMode check in
|
|
|
|
* src/mesa/main/context.c:check_compatible()
|
|
|
|
*/
|
|
|
|
if (dri2_config->dri_double_config)
|
|
|
|
dri_config = dri2_config->dri_double_config;
|
|
|
|
else
|
|
|
|
dri_config = dri2_config->dri_single_config;
|
2011-08-26 18:42:16 +01:00
|
|
|
|
|
|
|
/* EGL_WINDOW_BIT is set only when there is a dri_double_config. This
|
|
|
|
* makes sure the back buffer will always be used.
|
|
|
|
*/
|
|
|
|
if (conf->SurfaceType & EGL_WINDOW_BIT)
|
|
|
|
dri2_ctx->base.WindowRenderBuffer = EGL_BACK_BUFFER;
|
2011-02-09 14:30:20 +00:00
|
|
|
}
|
2010-07-27 23:25:54 +01:00
|
|
|
else
|
|
|
|
dri_config = NULL;
|
|
|
|
|
2011-02-17 04:05:15 +00:00
|
|
|
if (dri2_dpy->dri2) {
|
2012-07-18 22:41:28 +01:00
|
|
|
if (dri2_dpy->dri2->base.version >= 3) {
|
|
|
|
unsigned error;
|
2012-07-20 00:04:01 +01:00
|
|
|
unsigned num_attribs = 0;
|
|
|
|
uint32_t ctx_attribs[8];
|
|
|
|
|
|
|
|
ctx_attribs[num_attribs++] = __DRI_CTX_ATTRIB_MAJOR_VERSION;
|
|
|
|
ctx_attribs[num_attribs++] = dri2_ctx->base.ClientMajorVersion;
|
|
|
|
ctx_attribs[num_attribs++] = __DRI_CTX_ATTRIB_MINOR_VERSION;
|
|
|
|
ctx_attribs[num_attribs++] = dri2_ctx->base.ClientMinorVersion;
|
|
|
|
|
|
|
|
if (dri2_ctx->base.Flags != 0) {
|
|
|
|
/* If the implementation doesn't support the __DRI2_ROBUSTNESS
|
|
|
|
* extension, don't even try to send it the robust-access flag.
|
|
|
|
* It may explode. Instead, generate the required EGL error here.
|
|
|
|
*/
|
|
|
|
if ((dri2_ctx->base.Flags & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR) != 0
|
|
|
|
&& !dri2_dpy->robustness) {
|
|
|
|
_eglError(EGL_BAD_MATCH, "eglCreateContext");
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx_attribs[num_attribs++] = __DRI_CTX_ATTRIB_FLAGS;
|
|
|
|
ctx_attribs[num_attribs++] = dri2_ctx->base.Flags;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dri2_ctx->base.ResetNotificationStrategy != EGL_NO_RESET_NOTIFICATION_KHR) {
|
|
|
|
/* If the implementation doesn't support the __DRI2_ROBUSTNESS
|
|
|
|
* extension, don't even try to send it a reset strategy. It may
|
|
|
|
* explode. Instead, generate the required EGL error here.
|
|
|
|
*/
|
|
|
|
if (!dri2_dpy->robustness) {
|
|
|
|
_eglError(EGL_BAD_CONFIG, "eglCreateContext");
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx_attribs[num_attribs++] = __DRI_CTX_ATTRIB_RESET_STRATEGY;
|
|
|
|
ctx_attribs[num_attribs++] = __DRI_CTX_RESET_LOSE_CONTEXT;
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(num_attribs <= ARRAY_SIZE(ctx_attribs));
|
2012-07-18 22:41:28 +01:00
|
|
|
|
|
|
|
dri2_ctx->dri_context =
|
|
|
|
dri2_dpy->dri2->createContextAttribs(dri2_dpy->dri_screen,
|
|
|
|
api,
|
|
|
|
dri_config,
|
|
|
|
shared,
|
2012-07-20 00:04:01 +01:00
|
|
|
num_attribs / 2,
|
2012-07-18 22:41:28 +01:00
|
|
|
ctx_attribs,
|
|
|
|
& error,
|
|
|
|
dri2_ctx);
|
2012-11-09 22:06:41 +00:00
|
|
|
dri2_create_context_attribs_error(error);
|
2012-07-18 22:41:28 +01:00
|
|
|
} else {
|
2011-02-17 04:05:15 +00:00
|
|
|
dri2_ctx->dri_context =
|
|
|
|
dri2_dpy->dri2->createNewContextForAPI(dri2_dpy->dri_screen,
|
|
|
|
api,
|
|
|
|
dri_config,
|
2012-07-18 22:37:28 +01:00
|
|
|
shared,
|
2011-02-17 04:05:15 +00:00
|
|
|
dri2_ctx);
|
|
|
|
}
|
2010-04-27 16:38:46 +01:00
|
|
|
} else {
|
2011-02-17 04:05:15 +00:00
|
|
|
assert(dri2_dpy->swrast);
|
2012-07-18 18:08:49 +01:00
|
|
|
dri2_ctx->dri_context =
|
|
|
|
dri2_dpy->swrast->createNewContextForAPI(dri2_dpy->dri_screen,
|
|
|
|
api,
|
|
|
|
dri_config,
|
2012-07-18 22:37:28 +01:00
|
|
|
shared,
|
2012-07-18 18:08:49 +01:00
|
|
|
dri2_ctx);
|
2010-04-27 16:38:46 +01:00
|
|
|
}
|
2010-02-03 15:18:28 +00:00
|
|
|
|
2010-02-05 15:49:33 +00:00
|
|
|
if (!dri2_ctx->dri_context)
|
|
|
|
goto cleanup;
|
2010-02-03 15:18:28 +00:00
|
|
|
|
|
|
|
return &dri2_ctx->base;
|
2010-02-05 15:49:33 +00:00
|
|
|
|
|
|
|
cleanup:
|
|
|
|
free(dri2_ctx);
|
|
|
|
return NULL;
|
2010-02-03 15:18:28 +00:00
|
|
|
}
|
|
|
|
|
2011-08-14 08:14:17 +01:00
|
|
|
/**
|
|
|
|
* Called via eglDestroyContext(), drv->API.DestroyContext().
|
|
|
|
*/
|
|
|
|
static EGLBoolean
|
|
|
|
dri2_destroy_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx)
|
|
|
|
{
|
|
|
|
struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
|
|
|
|
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
|
|
|
|
|
|
|
if (_eglPutContext(ctx)) {
|
|
|
|
dri2_dpy->core->destroyContext(dri2_ctx->dri_context);
|
|
|
|
free(dri2_ctx);
|
|
|
|
}
|
|
|
|
|
|
|
|
return EGL_TRUE;
|
|
|
|
}
|
|
|
|
|
2010-02-03 15:18:28 +00:00
|
|
|
/**
|
|
|
|
* Called via eglMakeCurrent(), drv->API.MakeCurrent().
|
|
|
|
*/
|
|
|
|
static EGLBoolean
|
|
|
|
dri2_make_current(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf,
|
|
|
|
_EGLSurface *rsurf, _EGLContext *ctx)
|
|
|
|
{
|
2010-04-06 12:52:39 +01:00
|
|
|
struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
|
2010-02-03 15:18:28 +00:00
|
|
|
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
|
|
|
struct dri2_egl_surface *dri2_dsurf = dri2_egl_surface(dsurf);
|
|
|
|
struct dri2_egl_surface *dri2_rsurf = dri2_egl_surface(rsurf);
|
|
|
|
struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
|
2010-10-23 05:52:26 +01:00
|
|
|
_EGLContext *old_ctx;
|
|
|
|
_EGLSurface *old_dsurf, *old_rsurf;
|
2010-02-03 15:18:28 +00:00
|
|
|
__DRIdrawable *ddraw, *rdraw;
|
|
|
|
__DRIcontext *cctx;
|
|
|
|
|
2010-10-23 05:52:26 +01:00
|
|
|
/* make new bindings */
|
|
|
|
if (!_eglBindContext(ctx, dsurf, rsurf, &old_ctx, &old_dsurf, &old_rsurf))
|
2010-02-03 15:18:28 +00:00
|
|
|
return EGL_FALSE;
|
|
|
|
|
2010-04-06 12:52:39 +01:00
|
|
|
/* flush before context switch */
|
2010-10-26 08:00:56 +01:00
|
|
|
if (old_ctx && dri2_drv->glFlush)
|
2010-04-06 12:52:39 +01:00
|
|
|
dri2_drv->glFlush();
|
|
|
|
|
2010-02-03 15:18:28 +00:00
|
|
|
ddraw = (dri2_dsurf) ? dri2_dsurf->dri_drawable : NULL;
|
|
|
|
rdraw = (dri2_rsurf) ? dri2_rsurf->dri_drawable : NULL;
|
|
|
|
cctx = (dri2_ctx) ? dri2_ctx->dri_context : NULL;
|
|
|
|
|
2011-02-09 20:19:45 +00:00
|
|
|
if (old_ctx) {
|
|
|
|
__DRIcontext *old_cctx = dri2_egl_context(old_ctx)->dri_context;
|
|
|
|
dri2_dpy->core->unbindContext(old_cctx);
|
|
|
|
}
|
|
|
|
|
2010-02-03 15:18:28 +00:00
|
|
|
if ((cctx == NULL && ddraw == NULL && rdraw == NULL) ||
|
|
|
|
dri2_dpy->core->bindContext(cctx, ddraw, rdraw)) {
|
2011-02-09 20:19:45 +00:00
|
|
|
if (old_dsurf)
|
|
|
|
drv->API.DestroySurface(drv, disp, old_dsurf);
|
|
|
|
if (old_rsurf)
|
|
|
|
drv->API.DestroySurface(drv, disp, old_rsurf);
|
|
|
|
if (old_ctx)
|
2011-08-14 08:14:17 +01:00
|
|
|
drv->API.DestroyContext(drv, disp, old_ctx);
|
2010-02-03 15:18:28 +00:00
|
|
|
|
|
|
|
return EGL_TRUE;
|
|
|
|
} else {
|
2010-10-23 05:52:26 +01:00
|
|
|
/* undo the previous _eglBindContext */
|
|
|
|
_eglBindContext(old_ctx, old_dsurf, old_rsurf, &ctx, &dsurf, &rsurf);
|
|
|
|
assert(&dri2_ctx->base == ctx &&
|
|
|
|
&dri2_dsurf->base == dsurf &&
|
|
|
|
&dri2_rsurf->base == rsurf);
|
|
|
|
|
|
|
|
_eglPutSurface(dsurf);
|
|
|
|
_eglPutSurface(rsurf);
|
|
|
|
_eglPutContext(ctx);
|
|
|
|
|
|
|
|
_eglPutSurface(old_dsurf);
|
|
|
|
_eglPutSurface(old_rsurf);
|
|
|
|
_eglPutContext(old_ctx);
|
2010-02-03 15:18:28 +00:00
|
|
|
|
|
|
|
return EGL_FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Called from eglGetProcAddress() via drv->API.GetProcAddress().
|
|
|
|
*/
|
|
|
|
static _EGLProc
|
|
|
|
dri2_get_proc_address(_EGLDriver *drv, const char *procname)
|
|
|
|
{
|
2011-01-07 07:02:41 +00:00
|
|
|
struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
|
2010-02-03 15:18:28 +00:00
|
|
|
|
2011-01-07 07:02:41 +00:00
|
|
|
return dri2_drv->get_proc_address(procname);
|
2010-02-03 15:18:28 +00:00
|
|
|
}
|
|
|
|
|
2014-01-29 00:39:09 +00:00
|
|
|
static _EGLSurface*
|
|
|
|
dri2_create_window_surface(_EGLDriver *drv, _EGLDisplay *dpy,
|
egl/main: Stop using EGLNative types internally
Internally, much of the EGL code uses EGLNativeDisplayType,
EGLNativeWindowType, and EGLPixmapType. However, the EGLNative type
often does not match the variable's actual type.
The concept of EGLNative types are a bad match for Linux, as explained
below. And the EGL platform extensions don't use EGLNative types at all.
Those extensions attempt to solve cross-platform issues by moving the
EGL API away from the EGLNative types.
The core of the problem is that eglplatform.h can define each EGLNative
type once only, but Linux supports multiple EGL platforms.
To work around the problem, Mesa's eglplatform.h contains multiple
definitions of each EGLNative type, selected by feature macros. Mesa
expects EGL clients to set the feature macro approrpiately. But the
feature macros don't work when a single codebase must be built with
support for multiple EGL platforms, *such as Mesa itself*.
When building libEGL, autotools chooses the EGLNative typedefs based on
the first element of '--with-egl-platforms'. For example,
'--with-egl-platforms=x11,drm,wayland' defines the following:
typedef Display* EGLNativeDisplayType;
typedef Window EGLNativeWindowType;
typedef Pixmap EGLNativePixmapType;
Clearly, this doesn't work well for Wayland and GBM. Mesa works around
the problem by casting the EGLNative types to different things in
different files.
For sanity's sake, and to prepare for the EGL platform extensions, this
patch removes from egl/main and egl/dri2 all internal use of the
EGLNative types. It replaces them with 'void*' and checks each explicit
cast with a static assertion. Also, the patch touches egl_gallium the
minimal amount to keep it compatible with eglapi.h.
Signed-off-by: Chad Versace <chad.versace@linux.intel.com>
2014-01-07 22:54:51 +00:00
|
|
|
_EGLConfig *conf, void *native_window,
|
2014-01-29 00:39:09 +00:00
|
|
|
const EGLint *attrib_list)
|
|
|
|
{
|
|
|
|
struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
|
egl/main: Stop using EGLNative types internally
Internally, much of the EGL code uses EGLNativeDisplayType,
EGLNativeWindowType, and EGLPixmapType. However, the EGLNative type
often does not match the variable's actual type.
The concept of EGLNative types are a bad match for Linux, as explained
below. And the EGL platform extensions don't use EGLNative types at all.
Those extensions attempt to solve cross-platform issues by moving the
EGL API away from the EGLNative types.
The core of the problem is that eglplatform.h can define each EGLNative
type once only, but Linux supports multiple EGL platforms.
To work around the problem, Mesa's eglplatform.h contains multiple
definitions of each EGLNative type, selected by feature macros. Mesa
expects EGL clients to set the feature macro approrpiately. But the
feature macros don't work when a single codebase must be built with
support for multiple EGL platforms, *such as Mesa itself*.
When building libEGL, autotools chooses the EGLNative typedefs based on
the first element of '--with-egl-platforms'. For example,
'--with-egl-platforms=x11,drm,wayland' defines the following:
typedef Display* EGLNativeDisplayType;
typedef Window EGLNativeWindowType;
typedef Pixmap EGLNativePixmapType;
Clearly, this doesn't work well for Wayland and GBM. Mesa works around
the problem by casting the EGLNative types to different things in
different files.
For sanity's sake, and to prepare for the EGL platform extensions, this
patch removes from egl/main and egl/dri2 all internal use of the
EGLNative types. It replaces them with 'void*' and checks each explicit
cast with a static assertion. Also, the patch touches egl_gallium the
minimal amount to keep it compatible with eglapi.h.
Signed-off-by: Chad Versace <chad.versace@linux.intel.com>
2014-01-07 22:54:51 +00:00
|
|
|
return dri2_dpy->vtbl->create_window_surface(drv, dpy, conf, native_window,
|
2014-01-29 00:39:09 +00:00
|
|
|
attrib_list);
|
|
|
|
}
|
|
|
|
|
2014-01-29 00:45:07 +00:00
|
|
|
static _EGLSurface*
|
|
|
|
dri2_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *dpy,
|
egl/main: Stop using EGLNative types internally
Internally, much of the EGL code uses EGLNativeDisplayType,
EGLNativeWindowType, and EGLPixmapType. However, the EGLNative type
often does not match the variable's actual type.
The concept of EGLNative types are a bad match for Linux, as explained
below. And the EGL platform extensions don't use EGLNative types at all.
Those extensions attempt to solve cross-platform issues by moving the
EGL API away from the EGLNative types.
The core of the problem is that eglplatform.h can define each EGLNative
type once only, but Linux supports multiple EGL platforms.
To work around the problem, Mesa's eglplatform.h contains multiple
definitions of each EGLNative type, selected by feature macros. Mesa
expects EGL clients to set the feature macro approrpiately. But the
feature macros don't work when a single codebase must be built with
support for multiple EGL platforms, *such as Mesa itself*.
When building libEGL, autotools chooses the EGLNative typedefs based on
the first element of '--with-egl-platforms'. For example,
'--with-egl-platforms=x11,drm,wayland' defines the following:
typedef Display* EGLNativeDisplayType;
typedef Window EGLNativeWindowType;
typedef Pixmap EGLNativePixmapType;
Clearly, this doesn't work well for Wayland and GBM. Mesa works around
the problem by casting the EGLNative types to different things in
different files.
For sanity's sake, and to prepare for the EGL platform extensions, this
patch removes from egl/main and egl/dri2 all internal use of the
EGLNative types. It replaces them with 'void*' and checks each explicit
cast with a static assertion. Also, the patch touches egl_gallium the
minimal amount to keep it compatible with eglapi.h.
Signed-off-by: Chad Versace <chad.versace@linux.intel.com>
2014-01-07 22:54:51 +00:00
|
|
|
_EGLConfig *conf, void *native_pixmap,
|
2014-01-29 00:45:07 +00:00
|
|
|
const EGLint *attrib_list)
|
|
|
|
{
|
|
|
|
struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
|
egl/main: Stop using EGLNative types internally
Internally, much of the EGL code uses EGLNativeDisplayType,
EGLNativeWindowType, and EGLPixmapType. However, the EGLNative type
often does not match the variable's actual type.
The concept of EGLNative types are a bad match for Linux, as explained
below. And the EGL platform extensions don't use EGLNative types at all.
Those extensions attempt to solve cross-platform issues by moving the
EGL API away from the EGLNative types.
The core of the problem is that eglplatform.h can define each EGLNative
type once only, but Linux supports multiple EGL platforms.
To work around the problem, Mesa's eglplatform.h contains multiple
definitions of each EGLNative type, selected by feature macros. Mesa
expects EGL clients to set the feature macro approrpiately. But the
feature macros don't work when a single codebase must be built with
support for multiple EGL platforms, *such as Mesa itself*.
When building libEGL, autotools chooses the EGLNative typedefs based on
the first element of '--with-egl-platforms'. For example,
'--with-egl-platforms=x11,drm,wayland' defines the following:
typedef Display* EGLNativeDisplayType;
typedef Window EGLNativeWindowType;
typedef Pixmap EGLNativePixmapType;
Clearly, this doesn't work well for Wayland and GBM. Mesa works around
the problem by casting the EGLNative types to different things in
different files.
For sanity's sake, and to prepare for the EGL platform extensions, this
patch removes from egl/main and egl/dri2 all internal use of the
EGLNative types. It replaces them with 'void*' and checks each explicit
cast with a static assertion. Also, the patch touches egl_gallium the
minimal amount to keep it compatible with eglapi.h.
Signed-off-by: Chad Versace <chad.versace@linux.intel.com>
2014-01-07 22:54:51 +00:00
|
|
|
return dri2_dpy->vtbl->create_pixmap_surface(drv, dpy, conf, native_pixmap,
|
2014-01-29 00:45:07 +00:00
|
|
|
attrib_list);
|
|
|
|
}
|
|
|
|
|
2014-01-29 01:03:03 +00:00
|
|
|
static _EGLSurface*
|
|
|
|
dri2_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *dpy,
|
|
|
|
_EGLConfig *conf, const EGLint *attrib_list)
|
|
|
|
{
|
|
|
|
struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
|
|
|
|
return dri2_dpy->vtbl->create_pbuffer_surface(drv, dpy, conf, attrib_list);
|
|
|
|
}
|
|
|
|
|
2014-01-29 01:03:03 +00:00
|
|
|
static EGLBoolean
|
|
|
|
dri2_destroy_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
|
|
|
|
{
|
|
|
|
struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
|
|
|
|
return dri2_dpy->vtbl->destroy_surface(drv, dpy, surf);
|
|
|
|
}
|
|
|
|
|
2014-01-28 20:34:19 +00:00
|
|
|
static EGLBoolean
|
|
|
|
dri2_swap_interval(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
|
|
|
|
EGLint interval)
|
|
|
|
{
|
|
|
|
struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
|
|
|
|
return dri2_dpy->vtbl->swap_interval(drv, dpy, surf, interval);
|
|
|
|
}
|
|
|
|
|
2014-01-29 00:21:21 +00:00
|
|
|
static EGLBoolean
|
|
|
|
dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
|
|
|
|
{
|
|
|
|
struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
|
|
|
|
return dri2_dpy->vtbl->swap_buffers(drv, dpy, surf);
|
|
|
|
}
|
|
|
|
|
2014-01-29 00:26:44 +00:00
|
|
|
static EGLBoolean
|
|
|
|
dri2_swap_buffers_with_damage(_EGLDriver *drv, _EGLDisplay *dpy,
|
|
|
|
_EGLSurface *surf,
|
|
|
|
const EGLint *rects, EGLint n_rects)
|
|
|
|
{
|
|
|
|
struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
|
|
|
|
return dri2_dpy->vtbl->swap_buffers_with_damage(drv, dpy, surf,
|
|
|
|
rects, n_rects);
|
|
|
|
}
|
|
|
|
|
2014-01-29 01:03:03 +00:00
|
|
|
static EGLBoolean
|
|
|
|
dri2_swap_buffers_region(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
|
|
|
|
EGLint numRects, const EGLint *rects)
|
|
|
|
{
|
|
|
|
struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
|
|
|
|
return dri2_dpy->vtbl->swap_buffers_region(drv, dpy, surf, numRects, rects);
|
|
|
|
}
|
|
|
|
|
2014-01-29 01:03:03 +00:00
|
|
|
static EGLBoolean
|
|
|
|
dri2_post_sub_buffer(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
|
|
|
|
EGLint x, EGLint y, EGLint width, EGLint height)
|
|
|
|
{
|
|
|
|
struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
|
|
|
|
return dri2_dpy->vtbl->post_sub_buffer(drv, dpy, surf, x, y, width, height);
|
|
|
|
}
|
|
|
|
|
2014-01-29 01:03:03 +00:00
|
|
|
static EGLBoolean
|
|
|
|
dri2_copy_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
|
egl/main: Stop using EGLNative types internally
Internally, much of the EGL code uses EGLNativeDisplayType,
EGLNativeWindowType, and EGLPixmapType. However, the EGLNative type
often does not match the variable's actual type.
The concept of EGLNative types are a bad match for Linux, as explained
below. And the EGL platform extensions don't use EGLNative types at all.
Those extensions attempt to solve cross-platform issues by moving the
EGL API away from the EGLNative types.
The core of the problem is that eglplatform.h can define each EGLNative
type once only, but Linux supports multiple EGL platforms.
To work around the problem, Mesa's eglplatform.h contains multiple
definitions of each EGLNative type, selected by feature macros. Mesa
expects EGL clients to set the feature macro approrpiately. But the
feature macros don't work when a single codebase must be built with
support for multiple EGL platforms, *such as Mesa itself*.
When building libEGL, autotools chooses the EGLNative typedefs based on
the first element of '--with-egl-platforms'. For example,
'--with-egl-platforms=x11,drm,wayland' defines the following:
typedef Display* EGLNativeDisplayType;
typedef Window EGLNativeWindowType;
typedef Pixmap EGLNativePixmapType;
Clearly, this doesn't work well for Wayland and GBM. Mesa works around
the problem by casting the EGLNative types to different things in
different files.
For sanity's sake, and to prepare for the EGL platform extensions, this
patch removes from egl/main and egl/dri2 all internal use of the
EGLNative types. It replaces them with 'void*' and checks each explicit
cast with a static assertion. Also, the patch touches egl_gallium the
minimal amount to keep it compatible with eglapi.h.
Signed-off-by: Chad Versace <chad.versace@linux.intel.com>
2014-01-07 22:54:51 +00:00
|
|
|
void *native_pixmap_target)
|
2014-01-29 01:03:03 +00:00
|
|
|
{
|
|
|
|
struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
|
egl/main: Stop using EGLNative types internally
Internally, much of the EGL code uses EGLNativeDisplayType,
EGLNativeWindowType, and EGLPixmapType. However, the EGLNative type
often does not match the variable's actual type.
The concept of EGLNative types are a bad match for Linux, as explained
below. And the EGL platform extensions don't use EGLNative types at all.
Those extensions attempt to solve cross-platform issues by moving the
EGL API away from the EGLNative types.
The core of the problem is that eglplatform.h can define each EGLNative
type once only, but Linux supports multiple EGL platforms.
To work around the problem, Mesa's eglplatform.h contains multiple
definitions of each EGLNative type, selected by feature macros. Mesa
expects EGL clients to set the feature macro approrpiately. But the
feature macros don't work when a single codebase must be built with
support for multiple EGL platforms, *such as Mesa itself*.
When building libEGL, autotools chooses the EGLNative typedefs based on
the first element of '--with-egl-platforms'. For example,
'--with-egl-platforms=x11,drm,wayland' defines the following:
typedef Display* EGLNativeDisplayType;
typedef Window EGLNativeWindowType;
typedef Pixmap EGLNativePixmapType;
Clearly, this doesn't work well for Wayland and GBM. Mesa works around
the problem by casting the EGLNative types to different things in
different files.
For sanity's sake, and to prepare for the EGL platform extensions, this
patch removes from egl/main and egl/dri2 all internal use of the
EGLNative types. It replaces them with 'void*' and checks each explicit
cast with a static assertion. Also, the patch touches egl_gallium the
minimal amount to keep it compatible with eglapi.h.
Signed-off-by: Chad Versace <chad.versace@linux.intel.com>
2014-01-07 22:54:51 +00:00
|
|
|
return dri2_dpy->vtbl->copy_buffers(drv, dpy, surf, native_pixmap_target);
|
2014-01-29 01:03:03 +00:00
|
|
|
}
|
|
|
|
|
2014-01-29 01:03:03 +00:00
|
|
|
static EGLint
|
|
|
|
dri2_query_buffer_age(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
|
|
|
|
{
|
|
|
|
struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
|
|
|
|
return dri2_dpy->vtbl->query_buffer_age(drv, dpy, surf);
|
|
|
|
}
|
|
|
|
|
2010-02-03 15:18:28 +00:00
|
|
|
static EGLBoolean
|
2010-02-05 02:49:44 +00:00
|
|
|
dri2_wait_client(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx)
|
2010-02-03 15:18:28 +00:00
|
|
|
{
|
2010-02-05 02:49:44 +00:00
|
|
|
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
|
|
|
struct dri2_egl_surface *dri2_surf = dri2_egl_surface(ctx->DrawSurface);
|
|
|
|
|
2010-09-23 17:39:42 +01:00
|
|
|
(void) drv;
|
|
|
|
|
2010-02-05 02:49:44 +00:00
|
|
|
/* FIXME: If EGL allows frontbuffer rendering for window surfaces,
|
|
|
|
* we need to copy fake to real here.*/
|
|
|
|
|
2013-02-05 13:43:01 +00:00
|
|
|
if (dri2_dpy->flush != NULL)
|
|
|
|
dri2_dpy->flush->flush(dri2_surf->dri_drawable);
|
2010-02-03 15:18:28 +00:00
|
|
|
|
|
|
|
return EGL_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static EGLBoolean
|
2010-02-05 02:49:44 +00:00
|
|
|
dri2_wait_native(_EGLDriver *drv, _EGLDisplay *disp, EGLint engine)
|
2010-02-03 15:18:28 +00:00
|
|
|
{
|
2010-09-23 17:39:42 +01:00
|
|
|
(void) drv;
|
|
|
|
(void) disp;
|
|
|
|
|
2010-02-03 15:18:28 +00:00
|
|
|
if (engine != EGL_CORE_NATIVE_ENGINE)
|
|
|
|
return _eglError(EGL_BAD_PARAMETER, "eglWaitNative");
|
|
|
|
/* glXWaitX(); */
|
|
|
|
|
|
|
|
return EGL_TRUE;
|
|
|
|
}
|
|
|
|
|
2010-02-09 20:49:28 +00:00
|
|
|
static EGLBoolean
|
|
|
|
dri2_bind_tex_image(_EGLDriver *drv,
|
|
|
|
_EGLDisplay *disp, _EGLSurface *surf, EGLint buffer)
|
|
|
|
{
|
|
|
|
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
|
|
|
struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
|
|
|
|
struct dri2_egl_context *dri2_ctx;
|
|
|
|
_EGLContext *ctx;
|
|
|
|
GLint format, target;
|
|
|
|
|
|
|
|
ctx = _eglGetCurrentContext();
|
|
|
|
dri2_ctx = dri2_egl_context(ctx);
|
|
|
|
|
2010-05-07 03:40:25 +01:00
|
|
|
if (!_eglBindTexImage(drv, disp, surf, buffer))
|
2010-02-09 20:49:28 +00:00
|
|
|
return EGL_FALSE;
|
|
|
|
|
|
|
|
switch (dri2_surf->base.TextureFormat) {
|
|
|
|
case EGL_TEXTURE_RGB:
|
|
|
|
format = __DRI_TEXTURE_FORMAT_RGB;
|
|
|
|
break;
|
|
|
|
case EGL_TEXTURE_RGBA:
|
|
|
|
format = __DRI_TEXTURE_FORMAT_RGBA;
|
|
|
|
break;
|
|
|
|
default:
|
2010-05-07 03:40:25 +01:00
|
|
|
assert(0);
|
2010-02-09 20:49:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
switch (dri2_surf->base.TextureTarget) {
|
|
|
|
case EGL_TEXTURE_2D:
|
|
|
|
target = GL_TEXTURE_2D;
|
|
|
|
break;
|
|
|
|
default:
|
2010-05-07 03:40:25 +01:00
|
|
|
assert(0);
|
2010-02-09 20:49:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
(*dri2_dpy->tex_buffer->setTexBuffer2)(dri2_ctx->dri_context,
|
|
|
|
target, format,
|
|
|
|
dri2_surf->dri_drawable);
|
|
|
|
|
2010-05-07 03:40:25 +01:00
|
|
|
return EGL_TRUE;
|
2010-02-09 20:49:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static EGLBoolean
|
|
|
|
dri2_release_tex_image(_EGLDriver *drv,
|
|
|
|
_EGLDisplay *disp, _EGLSurface *surf, EGLint buffer)
|
|
|
|
{
|
2011-01-09 17:03:02 +00:00
|
|
|
#if __DRI_TEX_BUFFER_VERSION >= 3
|
|
|
|
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
|
|
|
struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
|
|
|
|
struct dri2_egl_context *dri2_ctx;
|
|
|
|
_EGLContext *ctx;
|
|
|
|
GLint target;
|
|
|
|
|
|
|
|
ctx = _eglGetCurrentContext();
|
|
|
|
dri2_ctx = dri2_egl_context(ctx);
|
|
|
|
|
|
|
|
if (!_eglReleaseTexImage(drv, disp, surf, buffer))
|
|
|
|
return EGL_FALSE;
|
|
|
|
|
|
|
|
switch (dri2_surf->base.TextureTarget) {
|
|
|
|
case EGL_TEXTURE_2D:
|
|
|
|
target = GL_TEXTURE_2D;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
assert(0);
|
|
|
|
}
|
|
|
|
if (dri2_dpy->tex_buffer->releaseTexBuffer!=NULL)
|
|
|
|
(*dri2_dpy->tex_buffer->releaseTexBuffer)(dri2_ctx->dri_context,
|
|
|
|
target,
|
|
|
|
dri2_surf->dri_drawable);
|
|
|
|
#endif
|
2010-09-23 17:39:42 +01:00
|
|
|
|
2010-02-09 20:49:28 +00:00
|
|
|
return EGL_TRUE;
|
|
|
|
}
|
|
|
|
|
2014-01-29 01:03:03 +00:00
|
|
|
static _EGLImage*
|
|
|
|
dri2_create_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx,
|
|
|
|
EGLenum target, EGLClientBuffer buffer,
|
|
|
|
const EGLint *attr_list)
|
|
|
|
{
|
|
|
|
struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
|
|
|
|
return dri2_dpy->vtbl->create_image(drv, dpy, ctx, target, buffer,
|
|
|
|
attr_list);
|
|
|
|
}
|
|
|
|
|
2010-02-26 19:51:11 +00:00
|
|
|
static _EGLImage *
|
2014-01-29 01:03:03 +00:00
|
|
|
dri2_create_image_from_dri(_EGLDisplay *disp, __DRIimage *dri_image)
|
2010-02-26 19:51:11 +00:00
|
|
|
{
|
|
|
|
struct dri2_egl_image *dri2_img;
|
|
|
|
|
2012-07-05 05:39:25 +01:00
|
|
|
if (dri_image == NULL) {
|
|
|
|
_eglError(EGL_BAD_ALLOC, "dri2_create_image");
|
|
|
|
return NULL;
|
2010-02-12 00:28:26 +00:00
|
|
|
}
|
|
|
|
|
2010-02-26 19:51:11 +00:00
|
|
|
dri2_img = malloc(sizeof *dri2_img);
|
|
|
|
if (!dri2_img) {
|
2012-07-05 05:39:25 +01:00
|
|
|
_eglError(EGL_BAD_ALLOC, "dri2_create_image");
|
|
|
|
return NULL;
|
2010-02-26 19:51:11 +00:00
|
|
|
}
|
|
|
|
|
2011-07-06 15:10:20 +01:00
|
|
|
if (!_eglInitImage(&dri2_img->base, disp)) {
|
|
|
|
free(dri2_img);
|
2012-07-05 05:39:25 +01:00
|
|
|
return NULL;
|
2011-07-06 15:10:20 +01:00
|
|
|
}
|
2010-02-26 19:51:11 +00:00
|
|
|
|
2012-07-05 05:39:25 +01:00
|
|
|
dri2_img->dri_image = dri_image;
|
2010-02-12 00:28:26 +00:00
|
|
|
|
|
|
|
return &dri2_img->base;
|
|
|
|
}
|
|
|
|
|
2010-06-04 02:36:40 +01:00
|
|
|
static _EGLImage *
|
2012-07-05 05:39:25 +01:00
|
|
|
dri2_create_image_khr_renderbuffer(_EGLDisplay *disp, _EGLContext *ctx,
|
|
|
|
EGLClientBuffer buffer,
|
|
|
|
const EGLint *attr_list)
|
2010-06-04 02:36:40 +01:00
|
|
|
{
|
|
|
|
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
2012-07-05 05:39:25 +01:00
|
|
|
struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
|
|
|
|
GLuint renderbuffer = (GLuint) (uintptr_t) buffer;
|
|
|
|
__DRIimage *dri_image;
|
2010-06-04 02:36:40 +01:00
|
|
|
|
2012-07-05 05:39:25 +01:00
|
|
|
if (renderbuffer == 0) {
|
|
|
|
_eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
|
|
|
|
return EGL_NO_IMAGE_KHR;
|
2010-06-04 02:36:40 +01:00
|
|
|
}
|
|
|
|
|
2012-07-05 05:39:25 +01:00
|
|
|
dri_image =
|
|
|
|
dri2_dpy->image->createImageFromRenderbuffer(dri2_ctx->dri_context,
|
|
|
|
renderbuffer, NULL);
|
2010-06-04 02:36:40 +01:00
|
|
|
|
2014-01-29 01:03:03 +00:00
|
|
|
return dri2_create_image_from_dri(disp, dri_image);
|
2010-06-04 02:36:40 +01:00
|
|
|
}
|
|
|
|
|
2013-11-10 18:32:01 +00:00
|
|
|
#ifdef HAVE_DRM_PLATFORM
|
2011-02-21 15:22:34 +00:00
|
|
|
static _EGLImage *
|
2012-01-10 22:16:26 +00:00
|
|
|
dri2_create_image_mesa_drm_buffer(_EGLDisplay *disp, _EGLContext *ctx,
|
|
|
|
EGLClientBuffer buffer, const EGLint *attr_list)
|
2011-02-21 15:22:34 +00:00
|
|
|
{
|
2012-07-05 05:39:25 +01:00
|
|
|
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
2012-01-10 22:16:26 +00:00
|
|
|
EGLint format, name, pitch, err;
|
|
|
|
_EGLImageAttribs attrs;
|
2012-07-05 05:39:25 +01:00
|
|
|
__DRIimage *dri_image;
|
2011-02-21 15:22:34 +00:00
|
|
|
|
2012-01-10 22:16:26 +00:00
|
|
|
name = (EGLint) (uintptr_t) buffer;
|
2011-02-21 15:22:34 +00:00
|
|
|
|
2012-01-10 22:16:26 +00:00
|
|
|
err = _eglParseImageAttribList(&attrs, disp, attr_list);
|
|
|
|
if (err != EGL_SUCCESS)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (attrs.Width <= 0 || attrs.Height <= 0 ||
|
|
|
|
attrs.DRMBufferStrideMESA <= 0) {
|
|
|
|
_eglError(EGL_BAD_PARAMETER,
|
|
|
|
"bad width, height or stride");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (attrs.DRMBufferFormatMESA) {
|
|
|
|
case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA:
|
|
|
|
format = __DRI_IMAGE_FORMAT_ARGB8888;
|
|
|
|
pitch = attrs.DRMBufferStrideMESA;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
_eglError(EGL_BAD_PARAMETER,
|
|
|
|
"dri2_create_image_khr: unsupported pixmap depth");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-07-05 05:39:25 +01:00
|
|
|
dri_image =
|
|
|
|
dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen,
|
|
|
|
attrs.Width,
|
|
|
|
attrs.Height,
|
|
|
|
format,
|
|
|
|
name,
|
|
|
|
pitch,
|
|
|
|
NULL);
|
|
|
|
|
2014-01-29 01:03:03 +00:00
|
|
|
return dri2_create_image_from_dri(disp, dri_image);
|
2011-02-21 15:22:34 +00:00
|
|
|
}
|
2013-11-10 18:32:01 +00:00
|
|
|
#endif
|
2011-02-21 15:22:34 +00:00
|
|
|
|
2012-01-10 22:16:26 +00:00
|
|
|
#ifdef HAVE_WAYLAND_PLATFORM
|
2012-07-05 21:43:04 +01:00
|
|
|
|
|
|
|
/* This structure describes how a wl_buffer maps to one or more
|
|
|
|
* __DRIimages. A wl_drm_buffer stores the wl_drm format code and the
|
|
|
|
* offsets and strides of the planes in the buffer. This table maps a
|
|
|
|
* wl_drm format code to a description of the planes in the buffer
|
|
|
|
* that lets us create a __DRIimage for each of the planes. */
|
|
|
|
|
2012-08-31 18:48:26 +01:00
|
|
|
static const struct wl_drm_components_descriptor {
|
|
|
|
uint32_t dri_components;
|
2012-07-05 21:43:04 +01:00
|
|
|
EGLint components;
|
|
|
|
int nplanes;
|
2012-08-31 18:48:26 +01:00
|
|
|
} wl_drm_components[] = {
|
|
|
|
{ __DRI_IMAGE_COMPONENTS_RGB, EGL_TEXTURE_RGB, 1 },
|
|
|
|
{ __DRI_IMAGE_COMPONENTS_RGBA, EGL_TEXTURE_RGBA, 1 },
|
|
|
|
{ __DRI_IMAGE_COMPONENTS_Y_U_V, EGL_TEXTURE_Y_U_V_WL, 3 },
|
|
|
|
{ __DRI_IMAGE_COMPONENTS_Y_UV, EGL_TEXTURE_Y_UV_WL, 2 },
|
|
|
|
{ __DRI_IMAGE_COMPONENTS_Y_XUXV, EGL_TEXTURE_Y_XUXV_WL, 2 },
|
2012-07-05 21:43:04 +01:00
|
|
|
};
|
|
|
|
|
2011-02-21 15:22:34 +00:00
|
|
|
static _EGLImage *
|
|
|
|
dri2_create_image_wayland_wl_buffer(_EGLDisplay *disp, _EGLContext *ctx,
|
2011-04-30 10:17:01 +01:00
|
|
|
EGLClientBuffer _buffer,
|
2011-02-21 15:22:34 +00:00
|
|
|
const EGLint *attr_list)
|
|
|
|
{
|
2013-07-18 13:11:25 +01:00
|
|
|
struct wl_drm_buffer *buffer;
|
2012-01-10 22:16:26 +00:00
|
|
|
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
2012-08-31 18:48:26 +01:00
|
|
|
const struct wl_drm_components_descriptor *f;
|
2012-07-05 21:43:04 +01:00
|
|
|
__DRIimage *dri_image;
|
|
|
|
_EGLImageAttribs attrs;
|
|
|
|
EGLint err;
|
2012-08-31 18:48:26 +01:00
|
|
|
int32_t plane;
|
2011-02-21 15:22:34 +00:00
|
|
|
|
2013-09-26 20:25:11 +01:00
|
|
|
buffer = wayland_drm_buffer_get(dri2_dpy->wl_server_drm,
|
|
|
|
(struct wl_resource *) _buffer);
|
2013-07-18 13:11:25 +01:00
|
|
|
if (!buffer)
|
2011-04-30 10:17:01 +01:00
|
|
|
return NULL;
|
2011-02-21 15:22:34 +00:00
|
|
|
|
2012-07-05 21:43:04 +01:00
|
|
|
err = _eglParseImageAttribList(&attrs, disp, attr_list);
|
|
|
|
plane = attrs.PlaneWL;
|
|
|
|
if (err != EGL_SUCCESS) {
|
|
|
|
_eglError(EGL_BAD_PARAMETER, "dri2_create_image_wayland_wl_buffer");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
f = buffer->driver_format;
|
|
|
|
if (plane < 0 || plane >= f->nplanes) {
|
|
|
|
_eglError(EGL_BAD_PARAMETER,
|
|
|
|
"dri2_create_image_wayland_wl_buffer (plane out of bounds)");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-08-31 18:48:26 +01:00
|
|
|
dri_image = dri2_dpy->image->fromPlanar(buffer->driver_buffer, plane, NULL);
|
2012-07-05 21:43:04 +01:00
|
|
|
|
2012-08-31 18:48:26 +01:00
|
|
|
if (dri_image == NULL) {
|
|
|
|
_eglError(EGL_BAD_PARAMETER, "dri2_create_image_wayland_wl_buffer");
|
|
|
|
return NULL;
|
|
|
|
}
|
2012-01-10 22:16:26 +00:00
|
|
|
|
2014-01-29 01:03:03 +00:00
|
|
|
return dri2_create_image_from_dri(disp, dri_image);
|
2011-02-21 15:22:34 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2012-11-27 13:19:54 +00:00
|
|
|
/**
|
|
|
|
* Set the error code after a call to
|
|
|
|
* dri2_egl_image::dri_image::createImageFromTexture.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
dri2_create_image_khr_texture_error(int dri_error)
|
|
|
|
{
|
|
|
|
EGLint egl_error;
|
|
|
|
|
|
|
|
switch (dri_error) {
|
|
|
|
case __DRI_IMAGE_ERROR_SUCCESS:
|
|
|
|
return;
|
|
|
|
|
|
|
|
case __DRI_IMAGE_ERROR_BAD_ALLOC:
|
|
|
|
egl_error = EGL_BAD_ALLOC;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case __DRI_IMAGE_ERROR_BAD_MATCH:
|
|
|
|
egl_error = EGL_BAD_MATCH;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case __DRI_IMAGE_ERROR_BAD_PARAMETER:
|
|
|
|
egl_error = EGL_BAD_PARAMETER;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
assert(0);
|
|
|
|
egl_error = EGL_BAD_MATCH;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
_eglError(egl_error, "dri2_create_image_khr_texture");
|
|
|
|
}
|
|
|
|
|
|
|
|
static _EGLImage *
|
|
|
|
dri2_create_image_khr_texture(_EGLDisplay *disp, _EGLContext *ctx,
|
|
|
|
EGLenum target,
|
|
|
|
EGLClientBuffer buffer,
|
|
|
|
const EGLint *attr_list)
|
|
|
|
{
|
|
|
|
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
|
|
|
struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
|
|
|
|
struct dri2_egl_image *dri2_img;
|
|
|
|
GLuint texture = (GLuint) (uintptr_t) buffer;
|
|
|
|
_EGLImageAttribs attrs;
|
|
|
|
GLuint depth;
|
|
|
|
GLenum gl_target;
|
|
|
|
unsigned error;
|
|
|
|
|
|
|
|
if (texture == 0) {
|
|
|
|
_eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
|
|
|
|
return EGL_NO_IMAGE_KHR;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_eglParseImageAttribList(&attrs, disp, attr_list) != EGL_SUCCESS)
|
|
|
|
return EGL_NO_IMAGE_KHR;
|
|
|
|
|
|
|
|
switch (target) {
|
|
|
|
case EGL_GL_TEXTURE_2D_KHR:
|
|
|
|
depth = 0;
|
|
|
|
gl_target = GL_TEXTURE_2D;
|
|
|
|
break;
|
|
|
|
case EGL_GL_TEXTURE_3D_KHR:
|
|
|
|
depth = attrs.GLTextureZOffset;
|
|
|
|
gl_target = GL_TEXTURE_3D;
|
|
|
|
break;
|
|
|
|
case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
|
|
|
|
case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
|
|
|
|
case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
|
|
|
|
case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
|
|
|
|
case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
|
|
|
|
case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
|
|
|
|
depth = target - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR;
|
|
|
|
gl_target = GL_TEXTURE_CUBE_MAP;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
_eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
|
|
|
|
return EGL_NO_IMAGE_KHR;
|
|
|
|
}
|
|
|
|
|
|
|
|
dri2_img = malloc(sizeof *dri2_img);
|
|
|
|
if (!dri2_img) {
|
|
|
|
_eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
|
|
|
|
return EGL_NO_IMAGE_KHR;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!_eglInitImage(&dri2_img->base, disp)) {
|
|
|
|
_eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
|
|
|
|
free(dri2_img);
|
|
|
|
return EGL_NO_IMAGE_KHR;
|
|
|
|
}
|
|
|
|
|
|
|
|
dri2_img->dri_image =
|
|
|
|
dri2_dpy->image->createImageFromTexture(dri2_ctx->dri_context,
|
|
|
|
gl_target,
|
|
|
|
texture,
|
|
|
|
depth,
|
|
|
|
attrs.GLTextureLevel,
|
|
|
|
&error,
|
|
|
|
dri2_img);
|
|
|
|
dri2_create_image_khr_texture_error(error);
|
|
|
|
|
|
|
|
if (!dri2_img->dri_image) {
|
|
|
|
free(dri2_img);
|
|
|
|
return EGL_NO_IMAGE_KHR;
|
|
|
|
}
|
|
|
|
return &dri2_img->base;
|
|
|
|
}
|
|
|
|
|
2014-01-29 01:03:03 +00:00
|
|
|
static struct wl_buffer*
|
|
|
|
dri2_create_wayland_buffer_from_image(_EGLDriver *drv, _EGLDisplay *dpy,
|
|
|
|
_EGLImage *img)
|
|
|
|
{
|
|
|
|
struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
|
|
|
|
return dri2_dpy->vtbl->create_wayland_buffer_from_image(drv, dpy, img);
|
|
|
|
}
|
|
|
|
|
2013-11-10 18:32:01 +00:00
|
|
|
#ifdef HAVE_DRM_PLATFORM
|
2013-03-22 13:58:05 +00:00
|
|
|
static EGLBoolean
|
|
|
|
dri2_check_dma_buf_attribs(const _EGLImageAttribs *attrs)
|
|
|
|
{
|
|
|
|
unsigned i;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The spec says:
|
|
|
|
*
|
|
|
|
* "Required attributes and their values are as follows:
|
|
|
|
*
|
|
|
|
* * EGL_WIDTH & EGL_HEIGHT: The logical dimensions of the buffer in pixels
|
|
|
|
*
|
|
|
|
* * EGL_LINUX_DRM_FOURCC_EXT: The pixel format of the buffer, as specified
|
|
|
|
* by drm_fourcc.h and used as the pixel_format parameter of the
|
|
|
|
* drm_mode_fb_cmd2 ioctl."
|
|
|
|
*
|
|
|
|
* and
|
|
|
|
*
|
|
|
|
* "* If <target> is EGL_LINUX_DMA_BUF_EXT, and the list of attributes is
|
|
|
|
* incomplete, EGL_BAD_PARAMETER is generated."
|
|
|
|
*/
|
|
|
|
if (attrs->Width <= 0 || attrs->Height <= 0 ||
|
|
|
|
!attrs->DMABufFourCC.IsPresent) {
|
|
|
|
_eglError(EGL_BAD_PARAMETER, "attribute(s) missing");
|
|
|
|
return EGL_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Also:
|
|
|
|
*
|
|
|
|
* "If <target> is EGL_LINUX_DMA_BUF_EXT and one or more of the values
|
|
|
|
* specified for a plane's pitch or offset isn't supported by EGL,
|
|
|
|
* EGL_BAD_ACCESS is generated."
|
|
|
|
*/
|
|
|
|
for (i = 0; i < ARRAY_SIZE(attrs->DMABufPlanePitches); ++i) {
|
|
|
|
if (attrs->DMABufPlanePitches[i].IsPresent &&
|
|
|
|
attrs->DMABufPlanePitches[i].Value <= 0) {
|
|
|
|
_eglError(EGL_BAD_ACCESS, "invalid pitch");
|
|
|
|
return EGL_FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return EGL_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Returns the total number of file descriptors. Zero indicates an error. */
|
|
|
|
static unsigned
|
|
|
|
dri2_check_dma_buf_format(const _EGLImageAttribs *attrs)
|
|
|
|
{
|
|
|
|
unsigned i, plane_n;
|
|
|
|
|
|
|
|
switch (attrs->DMABufFourCC.Value) {
|
|
|
|
case DRM_FORMAT_RGB332:
|
|
|
|
case DRM_FORMAT_BGR233:
|
|
|
|
case DRM_FORMAT_XRGB4444:
|
|
|
|
case DRM_FORMAT_XBGR4444:
|
|
|
|
case DRM_FORMAT_RGBX4444:
|
|
|
|
case DRM_FORMAT_BGRX4444:
|
|
|
|
case DRM_FORMAT_ARGB4444:
|
|
|
|
case DRM_FORMAT_ABGR4444:
|
|
|
|
case DRM_FORMAT_RGBA4444:
|
|
|
|
case DRM_FORMAT_BGRA4444:
|
|
|
|
case DRM_FORMAT_XRGB1555:
|
|
|
|
case DRM_FORMAT_XBGR1555:
|
|
|
|
case DRM_FORMAT_RGBX5551:
|
|
|
|
case DRM_FORMAT_BGRX5551:
|
|
|
|
case DRM_FORMAT_ARGB1555:
|
|
|
|
case DRM_FORMAT_ABGR1555:
|
|
|
|
case DRM_FORMAT_RGBA5551:
|
|
|
|
case DRM_FORMAT_BGRA5551:
|
|
|
|
case DRM_FORMAT_RGB565:
|
|
|
|
case DRM_FORMAT_BGR565:
|
|
|
|
case DRM_FORMAT_RGB888:
|
|
|
|
case DRM_FORMAT_BGR888:
|
|
|
|
case DRM_FORMAT_XRGB8888:
|
|
|
|
case DRM_FORMAT_XBGR8888:
|
|
|
|
case DRM_FORMAT_RGBX8888:
|
|
|
|
case DRM_FORMAT_BGRX8888:
|
|
|
|
case DRM_FORMAT_ARGB8888:
|
|
|
|
case DRM_FORMAT_ABGR8888:
|
|
|
|
case DRM_FORMAT_RGBA8888:
|
|
|
|
case DRM_FORMAT_BGRA8888:
|
|
|
|
case DRM_FORMAT_XRGB2101010:
|
|
|
|
case DRM_FORMAT_XBGR2101010:
|
|
|
|
case DRM_FORMAT_RGBX1010102:
|
|
|
|
case DRM_FORMAT_BGRX1010102:
|
|
|
|
case DRM_FORMAT_ARGB2101010:
|
|
|
|
case DRM_FORMAT_ABGR2101010:
|
|
|
|
case DRM_FORMAT_RGBA1010102:
|
|
|
|
case DRM_FORMAT_BGRA1010102:
|
|
|
|
case DRM_FORMAT_YUYV:
|
|
|
|
case DRM_FORMAT_YVYU:
|
|
|
|
case DRM_FORMAT_UYVY:
|
|
|
|
case DRM_FORMAT_VYUY:
|
|
|
|
plane_n = 1;
|
|
|
|
break;
|
|
|
|
case DRM_FORMAT_NV12:
|
|
|
|
case DRM_FORMAT_NV21:
|
|
|
|
case DRM_FORMAT_NV16:
|
|
|
|
case DRM_FORMAT_NV61:
|
|
|
|
plane_n = 2;
|
|
|
|
break;
|
|
|
|
case DRM_FORMAT_YUV410:
|
|
|
|
case DRM_FORMAT_YVU410:
|
|
|
|
case DRM_FORMAT_YUV411:
|
|
|
|
case DRM_FORMAT_YVU411:
|
|
|
|
case DRM_FORMAT_YUV420:
|
|
|
|
case DRM_FORMAT_YVU420:
|
|
|
|
case DRM_FORMAT_YUV422:
|
|
|
|
case DRM_FORMAT_YVU422:
|
|
|
|
case DRM_FORMAT_YUV444:
|
|
|
|
case DRM_FORMAT_YVU444:
|
|
|
|
plane_n = 3;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
_eglError(EGL_BAD_ATTRIBUTE, "invalid format");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The spec says:
|
|
|
|
*
|
|
|
|
* "* If <target> is EGL_LINUX_DMA_BUF_EXT, and the list of attributes is
|
|
|
|
* incomplete, EGL_BAD_PARAMETER is generated."
|
|
|
|
*/
|
|
|
|
for (i = 0; i < plane_n; ++i) {
|
|
|
|
if (!attrs->DMABufPlaneFds[i].IsPresent ||
|
|
|
|
!attrs->DMABufPlaneOffsets[i].IsPresent ||
|
|
|
|
!attrs->DMABufPlanePitches[i].IsPresent) {
|
|
|
|
_eglError(EGL_BAD_PARAMETER, "plane attribute(s) missing");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The spec also says:
|
|
|
|
*
|
|
|
|
* "If <target> is EGL_LINUX_DMA_BUF_EXT, and the EGL_LINUX_DRM_FOURCC_EXT
|
|
|
|
* attribute indicates a single-plane format, EGL_BAD_ATTRIBUTE is
|
|
|
|
* generated if any of the EGL_DMA_BUF_PLANE1_* or EGL_DMA_BUF_PLANE2_*
|
|
|
|
* attributes are specified."
|
|
|
|
*/
|
|
|
|
for (i = plane_n; i < 3; ++i) {
|
|
|
|
if (attrs->DMABufPlaneFds[i].IsPresent ||
|
|
|
|
attrs->DMABufPlaneOffsets[i].IsPresent ||
|
|
|
|
attrs->DMABufPlanePitches[i].IsPresent) {
|
|
|
|
_eglError(EGL_BAD_ATTRIBUTE, "too many plane attributes");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return plane_n;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The spec says:
|
|
|
|
*
|
|
|
|
* "If eglCreateImageKHR is successful for a EGL_LINUX_DMA_BUF_EXT target,
|
|
|
|
* the EGL takes ownership of the file descriptor and is responsible for
|
|
|
|
* closing it, which it may do at any time while the EGLDisplay is
|
|
|
|
* initialized."
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
dri2_take_dma_buf_ownership(const int *fds, unsigned num_fds)
|
|
|
|
{
|
|
|
|
int already_closed[num_fds];
|
|
|
|
unsigned num_closed = 0;
|
|
|
|
unsigned i, j;
|
|
|
|
|
|
|
|
for (i = 0; i < num_fds; ++i) {
|
|
|
|
/**
|
|
|
|
* The same file descriptor can be referenced multiple times in case more
|
|
|
|
* than one plane is found in the same buffer, just with a different
|
|
|
|
* offset.
|
|
|
|
*/
|
|
|
|
for (j = 0; j < num_closed; ++j) {
|
|
|
|
if (already_closed[j] == fds[i])
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (j == num_closed) {
|
|
|
|
close(fds[i]);
|
|
|
|
already_closed[num_closed++] = fds[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static _EGLImage *
|
|
|
|
dri2_create_image_dma_buf(_EGLDisplay *disp, _EGLContext *ctx,
|
|
|
|
EGLClientBuffer buffer, const EGLint *attr_list)
|
|
|
|
{
|
|
|
|
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
|
|
|
_EGLImage *res;
|
|
|
|
EGLint err;
|
|
|
|
_EGLImageAttribs attrs;
|
|
|
|
__DRIimage *dri_image;
|
|
|
|
unsigned num_fds;
|
|
|
|
unsigned i;
|
|
|
|
int fds[3];
|
|
|
|
int pitches[3];
|
|
|
|
int offsets[3];
|
|
|
|
unsigned error;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The spec says:
|
|
|
|
*
|
|
|
|
* ""* If <target> is EGL_LINUX_DMA_BUF_EXT and <buffer> is not NULL, the
|
|
|
|
* error EGL_BAD_PARAMETER is generated."
|
|
|
|
*/
|
|
|
|
if (buffer != NULL) {
|
|
|
|
_eglError(EGL_BAD_PARAMETER, "buffer not NULL");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
err = _eglParseImageAttribList(&attrs, disp, attr_list);
|
|
|
|
if (err != EGL_SUCCESS) {
|
|
|
|
_eglError(err, "bad attribute");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!dri2_check_dma_buf_attribs(&attrs))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
num_fds = dri2_check_dma_buf_format(&attrs);
|
|
|
|
if (!num_fds)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
for (i = 0; i < num_fds; ++i) {
|
|
|
|
fds[i] = attrs.DMABufPlaneFds[i].Value;
|
|
|
|
pitches[i] = attrs.DMABufPlanePitches[i].Value;
|
|
|
|
offsets[i] = attrs.DMABufPlaneOffsets[i].Value;
|
|
|
|
}
|
|
|
|
|
|
|
|
dri_image =
|
|
|
|
dri2_dpy->image->createImageFromDmaBufs(dri2_dpy->dri_screen,
|
|
|
|
attrs.Width, attrs.Height, attrs.DMABufFourCC.Value,
|
|
|
|
fds, num_fds, pitches, offsets,
|
|
|
|
attrs.DMABufYuvColorSpaceHint.Value,
|
|
|
|
attrs.DMABufSampleRangeHint.Value,
|
|
|
|
attrs.DMABufChromaHorizontalSiting.Value,
|
|
|
|
attrs.DMABufChromaVerticalSiting.Value,
|
|
|
|
&error,
|
|
|
|
NULL);
|
|
|
|
dri2_create_image_khr_texture_error(error);
|
|
|
|
|
|
|
|
if (!dri_image)
|
|
|
|
return EGL_NO_IMAGE_KHR;
|
|
|
|
|
2014-01-29 01:03:03 +00:00
|
|
|
res = dri2_create_image_from_dri(disp, dri_image);
|
2013-03-22 13:58:05 +00:00
|
|
|
if (res)
|
|
|
|
dri2_take_dma_buf_ownership(fds, num_fds);
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-10 18:32:01 +00:00
|
|
|
#endif
|
2013-03-22 13:58:05 +00:00
|
|
|
|
2011-02-03 03:10:40 +00:00
|
|
|
_EGLImage *
|
2010-02-26 19:51:11 +00:00
|
|
|
dri2_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
|
|
|
|
_EGLContext *ctx, EGLenum target,
|
|
|
|
EGLClientBuffer buffer, const EGLint *attr_list)
|
|
|
|
{
|
2010-09-23 17:39:42 +01:00
|
|
|
(void) drv;
|
|
|
|
|
2010-02-26 19:51:11 +00:00
|
|
|
switch (target) {
|
2012-11-27 13:19:54 +00:00
|
|
|
case EGL_GL_TEXTURE_2D_KHR:
|
|
|
|
case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
|
|
|
|
case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
|
|
|
|
case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
|
|
|
|
case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
|
|
|
|
case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
|
|
|
|
case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
|
|
|
|
return dri2_create_image_khr_texture(disp, ctx, target, buffer, attr_list);
|
2010-02-26 19:51:11 +00:00
|
|
|
case EGL_GL_RENDERBUFFER_KHR:
|
|
|
|
return dri2_create_image_khr_renderbuffer(disp, ctx, buffer, attr_list);
|
2013-11-10 18:32:01 +00:00
|
|
|
#ifdef HAVE_DRM_PLATFORM
|
2010-06-04 02:36:40 +01:00
|
|
|
case EGL_DRM_BUFFER_MESA:
|
|
|
|
return dri2_create_image_mesa_drm_buffer(disp, ctx, buffer, attr_list);
|
2013-11-10 18:32:01 +00:00
|
|
|
#endif
|
2011-02-21 15:22:34 +00:00
|
|
|
#ifdef HAVE_WAYLAND_PLATFORM
|
|
|
|
case EGL_WAYLAND_BUFFER_WL:
|
|
|
|
return dri2_create_image_wayland_wl_buffer(disp, ctx, buffer, attr_list);
|
|
|
|
#endif
|
2013-11-10 18:32:01 +00:00
|
|
|
#ifdef HAVE_DRM_PLATFORM
|
2013-03-22 13:58:05 +00:00
|
|
|
case EGL_LINUX_DMA_BUF_EXT:
|
|
|
|
return dri2_create_image_dma_buf(disp, ctx, buffer, attr_list);
|
2013-11-10 18:32:01 +00:00
|
|
|
#endif
|
2010-02-26 19:51:11 +00:00
|
|
|
default:
|
|
|
|
_eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
|
|
|
|
return EGL_NO_IMAGE_KHR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-02-12 00:28:26 +00:00
|
|
|
static EGLBoolean
|
|
|
|
dri2_destroy_image_khr(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *image)
|
|
|
|
{
|
|
|
|
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
|
|
|
struct dri2_egl_image *dri2_img = dri2_egl_image(image);
|
|
|
|
|
2010-09-23 17:39:42 +01:00
|
|
|
(void) drv;
|
|
|
|
|
2010-02-12 00:28:26 +00:00
|
|
|
dri2_dpy->image->destroyImage(dri2_img->dri_image);
|
|
|
|
free(dri2_img);
|
|
|
|
|
|
|
|
return EGL_TRUE;
|
|
|
|
}
|
2010-02-09 20:49:28 +00:00
|
|
|
|
2013-11-10 18:32:01 +00:00
|
|
|
#ifdef HAVE_DRM_PLATFORM
|
2010-06-04 02:36:40 +01:00
|
|
|
static _EGLImage *
|
|
|
|
dri2_create_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp,
|
|
|
|
const EGLint *attr_list)
|
|
|
|
{
|
|
|
|
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
|
|
|
struct dri2_egl_image *dri2_img;
|
2010-10-22 10:09:40 +01:00
|
|
|
_EGLImageAttribs attrs;
|
|
|
|
unsigned int dri_use, valid_mask;
|
|
|
|
int format;
|
2010-06-04 02:36:40 +01:00
|
|
|
EGLint err = EGL_SUCCESS;
|
|
|
|
|
2010-09-23 17:39:42 +01:00
|
|
|
(void) drv;
|
|
|
|
|
2010-06-04 02:36:40 +01:00
|
|
|
dri2_img = malloc(sizeof *dri2_img);
|
|
|
|
if (!dri2_img) {
|
|
|
|
_eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
|
|
|
|
return EGL_NO_IMAGE_KHR;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!attr_list) {
|
|
|
|
err = EGL_BAD_PARAMETER;
|
|
|
|
goto cleanup_img;
|
|
|
|
}
|
|
|
|
|
2010-10-22 09:36:47 +01:00
|
|
|
if (!_eglInitImage(&dri2_img->base, disp)) {
|
2010-06-04 02:36:40 +01:00
|
|
|
err = EGL_BAD_PARAMETER;
|
|
|
|
goto cleanup_img;
|
|
|
|
}
|
|
|
|
|
2010-10-22 10:09:40 +01:00
|
|
|
err = _eglParseImageAttribList(&attrs, disp, attr_list);
|
|
|
|
if (err != EGL_SUCCESS)
|
|
|
|
goto cleanup_img;
|
2010-06-04 02:36:40 +01:00
|
|
|
|
2010-10-22 10:09:40 +01:00
|
|
|
if (attrs.Width <= 0 || attrs.Height <= 0) {
|
|
|
|
_eglLog(_EGL_WARNING, "bad width or height (%dx%d)",
|
|
|
|
attrs.Width, attrs.Height);
|
2010-06-04 02:36:40 +01:00
|
|
|
goto cleanup_img;
|
|
|
|
}
|
|
|
|
|
2010-10-22 10:09:40 +01:00
|
|
|
switch (attrs.DRMBufferFormatMESA) {
|
2010-06-04 02:36:40 +01:00
|
|
|
case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA:
|
|
|
|
format = __DRI_IMAGE_FORMAT_ARGB8888;
|
|
|
|
break;
|
|
|
|
default:
|
2010-10-22 10:09:40 +01:00
|
|
|
_eglLog(_EGL_WARNING, "bad image format value 0x%04x",
|
|
|
|
attrs.DRMBufferFormatMESA);
|
2010-06-04 02:36:40 +01:00
|
|
|
goto cleanup_img;
|
|
|
|
}
|
|
|
|
|
|
|
|
valid_mask =
|
|
|
|
EGL_DRM_BUFFER_USE_SCANOUT_MESA |
|
2011-05-06 15:31:18 +01:00
|
|
|
EGL_DRM_BUFFER_USE_SHARE_MESA |
|
|
|
|
EGL_DRM_BUFFER_USE_CURSOR_MESA;
|
2010-10-22 10:09:40 +01:00
|
|
|
if (attrs.DRMBufferUseMESA & ~valid_mask) {
|
|
|
|
_eglLog(_EGL_WARNING, "bad image use bit 0x%04x",
|
|
|
|
attrs.DRMBufferUseMESA & ~valid_mask);
|
2010-06-04 02:36:40 +01:00
|
|
|
goto cleanup_img;
|
|
|
|
}
|
|
|
|
|
|
|
|
dri_use = 0;
|
2010-10-22 10:09:40 +01:00
|
|
|
if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SHARE_MESA)
|
2010-06-04 02:36:40 +01:00
|
|
|
dri_use |= __DRI_IMAGE_USE_SHARE;
|
2010-10-22 10:09:40 +01:00
|
|
|
if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SCANOUT_MESA)
|
2010-06-04 02:36:40 +01:00
|
|
|
dri_use |= __DRI_IMAGE_USE_SCANOUT;
|
2011-05-06 15:31:18 +01:00
|
|
|
if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_CURSOR_MESA)
|
|
|
|
dri_use |= __DRI_IMAGE_USE_CURSOR;
|
2010-06-04 02:36:40 +01:00
|
|
|
|
|
|
|
dri2_img->dri_image =
|
|
|
|
dri2_dpy->image->createImage(dri2_dpy->dri_screen,
|
2010-10-22 10:09:40 +01:00
|
|
|
attrs.Width, attrs.Height,
|
|
|
|
format, dri_use, dri2_img);
|
2010-06-04 02:36:40 +01:00
|
|
|
if (dri2_img->dri_image == NULL) {
|
|
|
|
err = EGL_BAD_ALLOC;
|
|
|
|
goto cleanup_img;
|
|
|
|
}
|
|
|
|
|
|
|
|
return &dri2_img->base;
|
|
|
|
|
|
|
|
cleanup_img:
|
|
|
|
free(dri2_img);
|
|
|
|
_eglError(err, "dri2_create_drm_image_mesa");
|
|
|
|
|
|
|
|
return EGL_NO_IMAGE_KHR;
|
|
|
|
}
|
|
|
|
|
|
|
|
static EGLBoolean
|
|
|
|
dri2_export_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *img,
|
|
|
|
EGLint *name, EGLint *handle, EGLint *stride)
|
|
|
|
{
|
|
|
|
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
|
|
|
struct dri2_egl_image *dri2_img = dri2_egl_image(img);
|
|
|
|
|
2010-09-23 17:39:42 +01:00
|
|
|
(void) drv;
|
|
|
|
|
2010-06-04 02:36:40 +01:00
|
|
|
if (name && !dri2_dpy->image->queryImage(dri2_img->dri_image,
|
|
|
|
__DRI_IMAGE_ATTRIB_NAME, name)) {
|
|
|
|
_eglError(EGL_BAD_ALLOC, "dri2_export_drm_image_mesa");
|
|
|
|
return EGL_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (handle)
|
|
|
|
dri2_dpy->image->queryImage(dri2_img->dri_image,
|
|
|
|
__DRI_IMAGE_ATTRIB_HANDLE, handle);
|
|
|
|
|
|
|
|
if (stride)
|
|
|
|
dri2_dpy->image->queryImage(dri2_img->dri_image,
|
|
|
|
__DRI_IMAGE_ATTRIB_STRIDE, stride);
|
|
|
|
|
|
|
|
return EGL_TRUE;
|
|
|
|
}
|
2013-11-10 18:32:01 +00:00
|
|
|
#endif
|
2010-06-04 02:36:40 +01:00
|
|
|
|
2011-02-21 15:22:34 +00:00
|
|
|
#ifdef HAVE_WAYLAND_PLATFORM
|
2011-04-30 10:17:01 +01:00
|
|
|
|
2012-07-05 19:19:48 +01:00
|
|
|
static void
|
2013-02-02 17:26:12 +00:00
|
|
|
dri2_wl_reference_buffer(void *user_data, uint32_t name, int fd,
|
2012-07-05 19:19:48 +01:00
|
|
|
struct wl_drm_buffer *buffer)
|
2011-04-30 10:17:01 +01:00
|
|
|
{
|
|
|
|
_EGLDisplay *disp = user_data;
|
|
|
|
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
2012-08-31 18:48:26 +01:00
|
|
|
__DRIimage *img;
|
|
|
|
int i, dri_components = 0;
|
|
|
|
|
2013-02-02 17:26:12 +00:00
|
|
|
if (fd == -1)
|
|
|
|
img = dri2_dpy->image->createImageFromNames(dri2_dpy->dri_screen,
|
2013-07-18 13:11:25 +01:00
|
|
|
buffer->width,
|
|
|
|
buffer->height,
|
2013-02-02 17:26:12 +00:00
|
|
|
buffer->format,
|
|
|
|
(int*)&name, 1,
|
|
|
|
buffer->stride,
|
|
|
|
buffer->offset,
|
|
|
|
NULL);
|
|
|
|
else
|
|
|
|
img = dri2_dpy->image->createImageFromFds(dri2_dpy->dri_screen,
|
2013-07-18 13:11:25 +01:00
|
|
|
buffer->width,
|
|
|
|
buffer->height,
|
2013-02-02 17:26:12 +00:00
|
|
|
buffer->format,
|
|
|
|
&fd, 1,
|
|
|
|
buffer->stride,
|
|
|
|
buffer->offset,
|
|
|
|
NULL);
|
2012-08-31 18:48:26 +01:00
|
|
|
|
|
|
|
if (img == NULL)
|
|
|
|
return;
|
2011-08-31 21:45:04 +01:00
|
|
|
|
2012-08-31 18:48:26 +01:00
|
|
|
dri2_dpy->image->queryImage(img, __DRI_IMAGE_ATTRIB_COMPONENTS, &dri_components);
|
2012-07-05 21:43:04 +01:00
|
|
|
|
2012-08-31 18:48:26 +01:00
|
|
|
buffer->driver_format = NULL;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(wl_drm_components); i++)
|
|
|
|
if (wl_drm_components[i].dri_components == dri_components)
|
|
|
|
buffer->driver_format = &wl_drm_components[i];
|
2011-04-30 10:17:01 +01:00
|
|
|
|
2012-08-31 18:48:26 +01:00
|
|
|
if (buffer->driver_format == NULL)
|
|
|
|
dri2_dpy->image->destroyImage(img);
|
|
|
|
else
|
|
|
|
buffer->driver_buffer = img;
|
2011-04-30 10:17:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-07-05 19:19:48 +01:00
|
|
|
dri2_wl_release_buffer(void *user_data, struct wl_drm_buffer *buffer)
|
2011-04-30 10:17:01 +01:00
|
|
|
{
|
|
|
|
_EGLDisplay *disp = user_data;
|
|
|
|
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
|
|
|
|
2012-07-05 19:19:48 +01:00
|
|
|
dri2_dpy->image->destroyImage(buffer->driver_buffer);
|
2011-04-30 10:17:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static struct wayland_drm_callbacks wl_drm_callbacks = {
|
|
|
|
.authenticate = NULL,
|
|
|
|
.reference_buffer = dri2_wl_reference_buffer,
|
|
|
|
.release_buffer = dri2_wl_release_buffer
|
|
|
|
};
|
|
|
|
|
2011-02-21 15:22:34 +00:00
|
|
|
static EGLBoolean
|
|
|
|
dri2_bind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *disp,
|
|
|
|
struct wl_display *wl_dpy)
|
|
|
|
{
|
|
|
|
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
2013-02-02 17:26:12 +00:00
|
|
|
int ret, flags = 0;
|
|
|
|
uint64_t cap;
|
2011-02-21 15:22:34 +00:00
|
|
|
|
|
|
|
(void) drv;
|
|
|
|
|
|
|
|
if (dri2_dpy->wl_server_drm)
|
|
|
|
return EGL_FALSE;
|
|
|
|
|
2011-04-30 10:17:01 +01:00
|
|
|
wl_drm_callbacks.authenticate =
|
2014-01-28 19:41:46 +00:00
|
|
|
(int(*)(void *, uint32_t)) dri2_dpy->vtbl->authenticate;
|
2011-04-30 10:17:01 +01:00
|
|
|
|
2013-02-02 17:26:12 +00:00
|
|
|
ret = drmGetCap(dri2_dpy->fd, DRM_CAP_PRIME, &cap);
|
2013-03-19 17:20:36 +00:00
|
|
|
if (ret == 0 && cap == (DRM_PRIME_CAP_IMPORT | DRM_PRIME_CAP_EXPORT) &&
|
|
|
|
dri2_dpy->image->base.version >= 7 &&
|
|
|
|
dri2_dpy->image->createImageFromFds != NULL)
|
2013-02-02 17:26:12 +00:00
|
|
|
flags |= WAYLAND_DRM_PRIME;
|
|
|
|
|
2011-02-21 15:22:34 +00:00
|
|
|
dri2_dpy->wl_server_drm =
|
2011-04-30 10:17:01 +01:00
|
|
|
wayland_drm_init(wl_dpy, dri2_dpy->device_name,
|
2013-02-02 17:26:12 +00:00
|
|
|
&wl_drm_callbacks, disp, flags);
|
2011-02-21 15:22:34 +00:00
|
|
|
|
|
|
|
if (!dri2_dpy->wl_server_drm)
|
|
|
|
return EGL_FALSE;
|
|
|
|
|
2013-09-26 20:25:11 +01:00
|
|
|
/* We have to share the wl_drm instance with gbm, so gbm can convert
|
|
|
|
* wl_buffers to gbm bos. */
|
2013-10-11 23:30:09 +01:00
|
|
|
if (dri2_dpy->gbm_dri)
|
|
|
|
dri2_dpy->gbm_dri->wl_drm = dri2_dpy->wl_server_drm;
|
2013-09-26 20:25:11 +01:00
|
|
|
|
2011-02-21 15:22:34 +00:00
|
|
|
return EGL_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static EGLBoolean
|
|
|
|
dri2_unbind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *disp,
|
|
|
|
struct wl_display *wl_dpy)
|
|
|
|
{
|
|
|
|
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
|
|
|
|
|
|
|
(void) drv;
|
|
|
|
|
|
|
|
if (!dri2_dpy->wl_server_drm)
|
|
|
|
return EGL_FALSE;
|
|
|
|
|
2011-04-30 10:17:01 +01:00
|
|
|
wayland_drm_uninit(dri2_dpy->wl_server_drm);
|
2011-02-21 15:22:34 +00:00
|
|
|
dri2_dpy->wl_server_drm = NULL;
|
|
|
|
|
|
|
|
return EGL_TRUE;
|
|
|
|
}
|
2012-07-05 21:43:04 +01:00
|
|
|
|
|
|
|
static EGLBoolean
|
|
|
|
dri2_query_wayland_buffer_wl(_EGLDriver *drv, _EGLDisplay *disp,
|
2013-07-18 13:11:25 +01:00
|
|
|
struct wl_resource *buffer_resource,
|
2012-07-05 21:43:04 +01:00
|
|
|
EGLint attribute, EGLint *value)
|
|
|
|
{
|
2013-09-26 20:25:11 +01:00
|
|
|
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
|
2013-07-18 13:11:25 +01:00
|
|
|
struct wl_drm_buffer *buffer;
|
2012-08-31 18:48:26 +01:00
|
|
|
const struct wl_drm_components_descriptor *format;
|
2012-07-05 21:43:04 +01:00
|
|
|
|
2013-09-26 20:25:11 +01:00
|
|
|
buffer = wayland_drm_buffer_get(dri2_dpy->wl_server_drm, buffer_resource);
|
2013-07-18 13:11:25 +01:00
|
|
|
if (!buffer)
|
2012-07-05 21:43:04 +01:00
|
|
|
return EGL_FALSE;
|
|
|
|
|
|
|
|
format = buffer->driver_format;
|
2012-07-19 14:02:25 +01:00
|
|
|
switch (attribute) {
|
|
|
|
case EGL_TEXTURE_FORMAT:
|
2012-07-05 21:43:04 +01:00
|
|
|
*value = format->components;
|
|
|
|
return EGL_TRUE;
|
2012-07-19 14:02:25 +01:00
|
|
|
case EGL_WIDTH:
|
2013-07-18 13:11:25 +01:00
|
|
|
*value = buffer->width;
|
2013-04-10 11:36:24 +01:00
|
|
|
return EGL_TRUE;
|
2012-07-19 14:02:25 +01:00
|
|
|
case EGL_HEIGHT:
|
2013-07-18 13:11:25 +01:00
|
|
|
*value = buffer->height;
|
2013-04-10 11:36:24 +01:00
|
|
|
return EGL_TRUE;
|
2012-07-05 21:43:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return EGL_FALSE;
|
|
|
|
}
|
2011-02-21 15:22:34 +00:00
|
|
|
#endif
|
|
|
|
|
2011-01-07 07:02:41 +00:00
|
|
|
static void
|
|
|
|
dri2_unload(_EGLDriver *drv)
|
|
|
|
{
|
|
|
|
struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
|
2011-01-29 21:09:06 +00:00
|
|
|
|
|
|
|
if (dri2_drv->handle)
|
|
|
|
dlclose(dri2_drv->handle);
|
2011-01-07 07:02:41 +00:00
|
|
|
free(dri2_drv);
|
|
|
|
}
|
|
|
|
|
|
|
|
static EGLBoolean
|
|
|
|
dri2_load(_EGLDriver *drv)
|
|
|
|
{
|
|
|
|
struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
|
2012-01-24 16:34:42 +00:00
|
|
|
#ifdef HAVE_SHARED_GLAPI
|
2011-08-05 06:39:18 +01:00
|
|
|
#ifdef HAVE_ANDROID_PLATFORM
|
|
|
|
const char *libname = "libglapi.so";
|
|
|
|
#else
|
2011-01-29 21:09:06 +00:00
|
|
|
const char *libname = "libglapi.so.0";
|
2012-01-24 16:34:42 +00:00
|
|
|
#endif
|
|
|
|
#else
|
|
|
|
/*
|
|
|
|
* Both libGL.so and libglapi.so are glapi providers. There is no way to
|
|
|
|
* tell which one to load.
|
|
|
|
*/
|
|
|
|
const char *libname = NULL;
|
2011-01-29 21:09:06 +00:00
|
|
|
#endif
|
2011-01-07 07:02:41 +00:00
|
|
|
void *handle;
|
|
|
|
|
2011-01-29 21:09:06 +00:00
|
|
|
/* RTLD_GLOBAL to make sure glapi symbols are visible to DRI drivers */
|
|
|
|
handle = dlopen(libname, RTLD_LAZY | RTLD_GLOBAL);
|
2011-01-07 07:02:41 +00:00
|
|
|
if (handle) {
|
|
|
|
dri2_drv->get_proc_address = (_EGLProc (*)(const char *))
|
|
|
|
dlsym(handle, "_glapi_get_proc_address");
|
2011-01-29 21:09:06 +00:00
|
|
|
if (!dri2_drv->get_proc_address || !libname) {
|
|
|
|
/* no need to keep a reference */
|
|
|
|
dlclose(handle);
|
|
|
|
handle = NULL;
|
|
|
|
}
|
2011-01-07 07:02:41 +00:00
|
|
|
}
|
|
|
|
|
2011-01-29 21:09:06 +00:00
|
|
|
/* if glapi is not available, loading DRI drivers will fail */
|
2011-01-07 07:02:41 +00:00
|
|
|
if (!dri2_drv->get_proc_address) {
|
|
|
|
_eglLog(_EGL_WARNING, "DRI2: failed to find _glapi_get_proc_address");
|
|
|
|
return EGL_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
dri2_drv->glFlush = (void (*)(void))
|
|
|
|
dri2_drv->get_proc_address("glFlush");
|
|
|
|
|
2011-01-29 21:09:06 +00:00
|
|
|
dri2_drv->handle = handle;
|
|
|
|
|
2011-01-07 07:02:41 +00:00
|
|
|
return EGL_TRUE;
|
|
|
|
}
|
|
|
|
|
2010-02-03 15:18:28 +00:00
|
|
|
/**
|
|
|
|
* This is the main entrypoint into the driver, called by libEGL.
|
|
|
|
* Create a new _EGLDriver object and init its dispatch table.
|
|
|
|
*/
|
|
|
|
_EGLDriver *
|
2012-02-05 06:01:17 +00:00
|
|
|
_eglBuiltInDriverDRI2(const char *args)
|
2010-02-03 15:18:28 +00:00
|
|
|
{
|
|
|
|
struct dri2_egl_driver *dri2_drv;
|
|
|
|
|
2010-09-23 17:39:42 +01:00
|
|
|
(void) args;
|
|
|
|
|
2012-09-05 07:09:22 +01:00
|
|
|
dri2_drv = calloc(1, sizeof *dri2_drv);
|
2010-02-03 15:18:28 +00:00
|
|
|
if (!dri2_drv)
|
|
|
|
return NULL;
|
|
|
|
|
2011-07-06 15:10:20 +01:00
|
|
|
if (!dri2_load(&dri2_drv->base)) {
|
|
|
|
free(dri2_drv);
|
2011-01-07 07:02:41 +00:00
|
|
|
return NULL;
|
2011-07-06 15:10:20 +01:00
|
|
|
}
|
2011-01-07 07:02:41 +00:00
|
|
|
|
2010-02-03 15:18:28 +00:00
|
|
|
_eglInitDriverFallbacks(&dri2_drv->base);
|
|
|
|
dri2_drv->base.API.Initialize = dri2_initialize;
|
|
|
|
dri2_drv->base.API.Terminate = dri2_terminate;
|
|
|
|
dri2_drv->base.API.CreateContext = dri2_create_context;
|
2011-08-14 08:14:17 +01:00
|
|
|
dri2_drv->base.API.DestroyContext = dri2_destroy_context;
|
2010-02-03 15:18:28 +00:00
|
|
|
dri2_drv->base.API.MakeCurrent = dri2_make_current;
|
2014-01-29 00:39:09 +00:00
|
|
|
dri2_drv->base.API.CreateWindowSurface = dri2_create_window_surface;
|
2014-01-29 00:45:07 +00:00
|
|
|
dri2_drv->base.API.CreatePixmapSurface = dri2_create_pixmap_surface;
|
2014-01-29 01:03:03 +00:00
|
|
|
dri2_drv->base.API.CreatePbufferSurface = dri2_create_pbuffer_surface;
|
2014-01-29 01:03:03 +00:00
|
|
|
dri2_drv->base.API.DestroySurface = dri2_destroy_surface;
|
2010-02-03 15:18:28 +00:00
|
|
|
dri2_drv->base.API.GetProcAddress = dri2_get_proc_address;
|
|
|
|
dri2_drv->base.API.WaitClient = dri2_wait_client;
|
|
|
|
dri2_drv->base.API.WaitNative = dri2_wait_native;
|
2010-02-09 20:49:28 +00:00
|
|
|
dri2_drv->base.API.BindTexImage = dri2_bind_tex_image;
|
|
|
|
dri2_drv->base.API.ReleaseTexImage = dri2_release_tex_image;
|
2014-01-28 20:34:19 +00:00
|
|
|
dri2_drv->base.API.SwapInterval = dri2_swap_interval;
|
2014-01-29 00:21:21 +00:00
|
|
|
dri2_drv->base.API.SwapBuffers = dri2_swap_buffers;
|
2014-01-29 00:26:44 +00:00
|
|
|
dri2_drv->base.API.SwapBuffersWithDamageEXT = dri2_swap_buffers_with_damage;
|
2014-01-29 01:03:03 +00:00
|
|
|
dri2_drv->base.API.SwapBuffersRegionNOK = dri2_swap_buffers_region;
|
2014-01-29 01:03:03 +00:00
|
|
|
dri2_drv->base.API.PostSubBufferNV = dri2_post_sub_buffer;
|
2014-01-29 01:03:03 +00:00
|
|
|
dri2_drv->base.API.CopyBuffers = dri2_copy_buffers,
|
2014-01-29 01:03:03 +00:00
|
|
|
dri2_drv->base.API.QueryBufferAge = dri2_query_buffer_age;
|
2014-01-29 01:03:03 +00:00
|
|
|
dri2_drv->base.API.CreateImageKHR = dri2_create_image;
|
2010-02-12 00:28:26 +00:00
|
|
|
dri2_drv->base.API.DestroyImageKHR = dri2_destroy_image_khr;
|
2014-01-29 01:03:03 +00:00
|
|
|
dri2_drv->base.API.CreateWaylandBufferFromImageWL = dri2_create_wayland_buffer_from_image;
|
2013-11-10 18:32:01 +00:00
|
|
|
#ifdef HAVE_DRM_PLATFORM
|
2010-06-04 02:36:40 +01:00
|
|
|
dri2_drv->base.API.CreateDRMImageMESA = dri2_create_drm_image_mesa;
|
|
|
|
dri2_drv->base.API.ExportDRMImageMESA = dri2_export_drm_image_mesa;
|
2013-11-10 18:32:01 +00:00
|
|
|
#endif
|
2011-02-21 15:22:34 +00:00
|
|
|
#ifdef HAVE_WAYLAND_PLATFORM
|
|
|
|
dri2_drv->base.API.BindWaylandDisplayWL = dri2_bind_wayland_display_wl;
|
|
|
|
dri2_drv->base.API.UnbindWaylandDisplayWL = dri2_unbind_wayland_display_wl;
|
2012-07-05 21:43:04 +01:00
|
|
|
dri2_drv->base.API.QueryWaylandBufferWL = dri2_query_wayland_buffer_wl;
|
2011-02-21 15:22:34 +00:00
|
|
|
#endif
|
2010-02-03 15:18:28 +00:00
|
|
|
|
|
|
|
dri2_drv->base.Name = "DRI2";
|
|
|
|
dri2_drv->base.Unload = dri2_unload;
|
|
|
|
|
|
|
|
return &dri2_drv->base;
|
|
|
|
}
|