[Mesa-dev] [PATCH 2/2] egl_dri2: Adding swrast and refactoring
Kristian Høgsberg
krh at bitplanet.net
Thu Feb 3 08:54:58 PST 2011
On Sun, Jan 30, 2011 at 3:05 AM, Feng, Haitao <haitao.feng at intel.com> wrote:
> From f723112e2d10429e9691a547baeab588d45511d6 Mon Sep 17 00:00:00 2001
> From: Haitao Feng <haitao.feng at intel.com>
> Date: Sat, 29 Jan 2011 23:50:01 -0800
> Subject: [PATCH 2/2] egl_dri2: Adding swrast and refactoring
>
> This enables the egl_dri2 driver to load swrast driver
> for software rendering. It could be used when hardware
> dri2 driver is not available, such as in VM. After the
> swrast enabling, I refactor the code as egl image functions
> are not supported in swrast and egl surface functions
> are not supported in drm. After refactoring, egl_dri2.c
> contains functions shared between drm, x11_dri2 and
> x11_swrast. dri2_shared.c contains functions shared between
> drm and x11_dri2. x11_shared.c contains functions shared
> between x11_dri2 and x11_swrast.
>
> Note: this is a candidate for the 7.9 branch.
Hi Haitao,
Thanks for adding swrast support to egl_dri2.c. The overall approach
looks good, though I'm not sure we need to split it up quite that
much. However for something like this we really need to break it down
into a series of patches. The patch here splits out the different
platforms and then adds the swrast functionality, but it would be
better if it was a patch to split out shared code, a patch split out
the x11 platform, and patch to split out the drm platform, and then
the patch to add swrast. It makes it easer to review the patches
since all the code motion is in separate patches and the meat of the
series, the swrast addition, will have each own patch. It also makes
bisecting possible and you're less likely to hit the mailing size
limit.
Also, the patch looks like it's against mesa 7.9. I know that's what
we ship in meego and where we need the swrast functionality, but for
submitting upstream, we need a patch against mesa master. We can ship
the patch in the meego rpm, but we can't add a feature like this in a
stable mesa branch. The patch doesn't apply against mesa master, and
since a lot changed in egl_dri2.c since 7.9, I think the best approach
is to just redo the split and then add the swrast functionality. I've
split up egl_dri2.c in mesa master like this:
egl_dri2.h - header file for everything
egl_dri2.c - shared code
platform_x11.c code related to the x11 platform
platform_drm.c code related to the drm platform
and I imagine we can just add swrast in platform_x11.c. Is that
doable you think?
Kristian
> Signed-off-by: Haitao Feng <haitao.feng at intel.com>
> ---
> src/egl/drivers/dri2/Makefile | 2 +-
> src/egl/drivers/dri2/dri2_shared.c | 390 ++++++++
> src/egl/drivers/dri2/dri2_shared.h | 64 ++
> src/egl/drivers/dri2/drm_dri2.c | 250 ++++++
> src/egl/drivers/dri2/egl_dri2.c | 1740 +++++-------------------------------
> src/egl/drivers/dri2/egl_dri2.h | 148 +++
> src/egl/drivers/dri2/x11_dri2.c | 745 +++++++++++++++
> src/egl/drivers/dri2/x11_shared.c | 132 +++
> src/egl/drivers/dri2/x11_shared.h | 81 ++
> src/egl/drivers/dri2/x11_swrast.c | 486 ++++++++++
> 10 files changed, 2517 insertions(+), 1521 deletions(-)
> create mode 100644 src/egl/drivers/dri2/dri2_shared.c
> create mode 100644 src/egl/drivers/dri2/dri2_shared.h
> create mode 100644 src/egl/drivers/dri2/drm_dri2.c
> create mode 100644 src/egl/drivers/dri2/egl_dri2.h
> create mode 100644 src/egl/drivers/dri2/x11_dri2.c
> create mode 100644 src/egl/drivers/dri2/x11_shared.c
> create mode 100644 src/egl/drivers/dri2/x11_shared.h
> create mode 100644 src/egl/drivers/dri2/x11_swrast.c
>
> diff --git a/src/egl/drivers/dri2/Makefile b/src/egl/drivers/dri2/Makefile
> index 8a3c9b6..7fe121d 100644
> --- a/src/egl/drivers/dri2/Makefile
> +++ b/src/egl/drivers/dri2/Makefile
> @@ -4,7 +4,7 @@ TOP = ../../../..
> include $(TOP)/configs/current
>
> EGL_DRIVER = egl_dri2.so
> -EGL_SOURCES = egl_dri2.c
> +EGL_SOURCES = egl_dri2.c dri2_shared.c x11_shared.c drm_dri2.c x11_dri2.c x11_swrast.c
>
> EGL_INCLUDES = \
> -I$(TOP)/include \
> diff --git a/src/egl/drivers/dri2/dri2_shared.c b/src/egl/drivers/dri2/dri2_shared.c
> new file mode 100644
> index 0000000..38ed182
> --- /dev/null
> +++ b/src/egl/drivers/dri2/dri2_shared.c
> @@ -0,0 +1,390 @@
> +/*
> + * 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 at bitplanet.net>
> + */
> +
> +#include "dri2_shared.h"
> +
> +struct dri2_extension_match dri2_driver_extensions[] = {
> + { __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) },
> + { __DRI_DRI2, 1, offsetof(struct dri2_egl_display, dri2) },
> + { NULL }
> +};
> +
> +struct dri2_extension_match dri2_core_extensions[] = {
> + { __DRI2_FLUSH, 1, offsetof(struct dri2_egl_display, flush) },
> + { __DRI_TEX_BUFFER, 2, offsetof(struct dri2_egl_display, tex_buffer) },
> + { __DRI_IMAGE, 1, offsetof(struct dri2_egl_display, image) },
> + { NULL }
> +};
> +
> +__DRIimage *
> +dri2_lookup_egl_image(__DRIscreen *screen, void *image, void *data)
> +{
> + _EGLDisplay *disp = data;
> + struct dri2_egl_image *dri2_img;
> + _EGLImage *img;
> +
> + 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;
> +}
> +
> +const __DRIimageLookupExtension image_lookup_extension = {
> + { __DRI_IMAGE_LOOKUP, 1 },
> + dri2_lookup_egl_image
> +};
> +
> +EGLBoolean
> +dri2_create_screen(_EGLDisplay *disp)
> +{
> + const __DRIextension **extensions;
> + struct dri2_egl_display *dri2_dpy;
> + unsigned int api_mask;
> +
> + dri2_dpy = disp->DriverData;
> + dri2_dpy->dri_screen =
> + dri2_dpy->dri2->createNewScreen(0, dri2_dpy->fd, dri2_dpy->extensions,
> + &dri2_dpy->driver_configs, disp);
> +
> + if (dri2_dpy->dri_screen == NULL) {
> + _eglLog(_EGL_WARNING, "DRI2: failed to create dri screen");
> + return EGL_FALSE;
> + }
> +
> + extensions = dri2_dpy->core->getExtensions(dri2_dpy->dri_screen);
> + if (!dri2_bind_extensions(dri2_dpy, dri2_core_extensions, extensions))
> + goto cleanup_dri_screen;
> +
> + if (dri2_dpy->dri2->base.version >= 2)
> + api_mask = dri2_dpy->dri2->getAPIMask(dri2_dpy->dri_screen);
> + else
> + api_mask = 1 << __DRI_API_OPENGL;
> +
> + disp->ClientAPIsMask = 0;
> + if (api_mask & (1 <<__DRI_API_OPENGL))
> + disp->ClientAPIsMask |= EGL_OPENGL_BIT;
> + if (api_mask & (1 <<__DRI_API_GLES))
> + disp->ClientAPIsMask |= EGL_OPENGL_ES_BIT;
> + if (api_mask & (1 << __DRI_API_GLES2))
> + disp->ClientAPIsMask |= EGL_OPENGL_ES2_BIT;
> +
> + if (dri2_dpy->dri2->base.version >= 2) {
> + disp->Extensions.KHR_surfaceless_gles1 = EGL_TRUE;
> + disp->Extensions.KHR_surfaceless_gles2 = EGL_TRUE;
> + disp->Extensions.KHR_surfaceless_opengl = EGL_TRUE;
> + }
> +
> + return EGL_TRUE;
> +
> + cleanup_dri_screen:
> + dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
> +
> + return EGL_FALSE;
> +}
> +
> +_EGLImage *
> +dri2_create_image_khr_renderbuffer(_EGLDisplay *disp, _EGLContext *ctx,
> + 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 renderbuffer = (GLuint) buffer;
> +
> + if (renderbuffer == 0) {
> + _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, attr_list))
> + return EGL_NO_IMAGE_KHR;
> +
> + dri2_img->dri_image =
> + dri2_dpy->image->createImageFromRenderbuffer(dri2_ctx->dri_context,
> + renderbuffer,
> + dri2_img);
> +
> + return &dri2_img->base;
> +}
> +
> +_EGLImage *
> +dri2_create_image_mesa_drm_buffer(_EGLDisplay *disp, _EGLContext *ctx,
> + EGLClientBuffer buffer, const EGLint *attr_list)
> +{
> + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
> + struct dri2_egl_image *dri2_img;
> + EGLint width, height, format, name, stride, pitch, i, err;
> +
> + name = (EGLint) buffer;
> +
> + err = EGL_SUCCESS;
> + width = 0;
> + height = 0;
> + format = 0;
> + stride = 0;
> +
> + for (i = 0; attr_list[i] != EGL_NONE; i++) {
> + EGLint attr = attr_list[i++];
> + EGLint val = attr_list[i];
> +
> + switch (attr) {
> + case EGL_WIDTH:
> + width = val;
> + break;
> + case EGL_HEIGHT:
> + height = val;
> + break;
> + case EGL_DRM_BUFFER_FORMAT_MESA:
> + format = val;
> + break;
> + case EGL_DRM_BUFFER_STRIDE_MESA:
> + stride = val;
> + break;
> + default:
> + err = EGL_BAD_ATTRIBUTE;
> + break;
> + }
> +
> + if (err != EGL_SUCCESS) {
> + _eglLog(_EGL_WARNING, "bad image attribute 0x%04x", attr);
> + return NULL;
> + }
> + }
> +
> + if (width <= 0 || height <= 0 || stride <= 0) {
> + _eglError(EGL_BAD_PARAMETER,
> + "bad width, height or stride");
> + return NULL;
> + }
> +
> + switch (format) {
> + case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA:
> + format = __DRI_IMAGE_FORMAT_ARGB8888;
> + pitch = stride;
> + break;
> + default:
> + _eglError(EGL_BAD_PARAMETER,
> + "dri2_create_image_khr: unsupported pixmap depth");
> + return NULL;
> + }
> +
> + dri2_img = malloc(sizeof *dri2_img);
> + if (!dri2_img) {
> + _eglError(EGL_BAD_ALLOC, "dri2_create_image_mesa_drm");
> + return NULL;
> + }
> +
> + if (!_eglInitImage(&dri2_img->base, disp, attr_list)) {
> + free(dri2_img);
> + return NULL;
> + }
> +
> + dri2_img->dri_image =
> + dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen,
> + width,
> + height,
> + format,
> + name,
> + pitch,
> + dri2_img);
> + if (dri2_img->dri_image == NULL) {
> + free(dri2_img);
> + _eglError(EGL_BAD_ALLOC, "dri2_create_image_mesa_drm");
> + return NULL;
> + }
> +
> + return &dri2_img->base;
> +}
> +
> +_EGLImage *
> +dri2_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
> + _EGLContext *ctx, EGLenum target,
> + EGLClientBuffer buffer, const EGLint *attr_list)
> +{
> + switch (target) {
> + case EGL_GL_RENDERBUFFER_KHR:
> + return dri2_create_image_khr_renderbuffer(disp, ctx, buffer, attr_list);
> + case EGL_DRM_BUFFER_MESA:
> + return dri2_create_image_mesa_drm_buffer(disp, ctx, buffer, attr_list);
> + default:
> + _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
> + return EGL_NO_IMAGE_KHR;
> + }
> +}
> +
> +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);
> +
> + dri2_dpy->image->destroyImage(dri2_img->dri_image);
> + free(dri2_img);
> +
> + return EGL_TRUE;
> +}
> +
> +_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;
> + int width, height, format, i;
> + unsigned int use, dri_use, valid_mask;
> +
> + EGLint err = EGL_SUCCESS;
> +
> + 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;
> + }
> +
> + if (!_eglInitImage(&dri2_img->base, disp, attr_list)) {
> + err = EGL_BAD_PARAMETER;
> + goto cleanup_img;
> + }
> +
> + width = 0;
> + height = 0;
> + format = 0;
> + use = 0;
> + for (i = 0; attr_list[i] != EGL_NONE; i++) {
> + EGLint attr = attr_list[i++];
> + EGLint val = attr_list[i];
> +
> + switch (attr) {
> + case EGL_WIDTH:
> + width = val;
> + break;
> + case EGL_HEIGHT:
> + height = val;
> + break;
> + case EGL_DRM_BUFFER_FORMAT_MESA:
> + format = val;
> + break;
> + case EGL_DRM_BUFFER_USE_MESA:
> + use = val;
> + break;
> + default:
> + err = EGL_BAD_ATTRIBUTE;
> + break;
> + }
> +
> + if (err != EGL_SUCCESS) {
> + _eglLog(_EGL_WARNING, "bad image attribute 0x%04x", attr);
> + goto cleanup_img;
> + }
> + }
> +
> + if (width <= 0 || height <= 0) {
> + _eglLog(_EGL_WARNING, "bad width or height (%dx%d)", width, height);
> + goto cleanup_img;
> + }
> +
> + switch (format) {
> + case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA:
> + format = __DRI_IMAGE_FORMAT_ARGB8888;
> + break;
> + default:
> + _eglLog(_EGL_WARNING, "bad image format value 0x%04x", format);
> + goto cleanup_img;
> + }
> +
> + valid_mask =
> + EGL_DRM_BUFFER_USE_SCANOUT_MESA |
> + EGL_DRM_BUFFER_USE_SHARE_MESA;
> + if (use & ~valid_mask) {
> + _eglLog(_EGL_WARNING, "bad image use bit 0x%04x", use & ~valid_mask);
> + goto cleanup_img;
> + }
> +
> + dri_use = 0;
> + if (use & EGL_DRM_BUFFER_USE_SHARE_MESA)
> + dri_use |= __DRI_IMAGE_USE_SHARE;
> + if (use & EGL_DRM_BUFFER_USE_SCANOUT_MESA)
> + dri_use |= __DRI_IMAGE_USE_SCANOUT;
> +
> + dri2_img->dri_image =
> + dri2_dpy->image->createImage(dri2_dpy->dri_screen,
> + width, height, format, dri_use, dri2_img);
> + 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;
> +}
> +
> +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);
> +
> + 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;
> +}
> +
> diff --git a/src/egl/drivers/dri2/dri2_shared.h b/src/egl/drivers/dri2/dri2_shared.h
> new file mode 100644
> index 0000000..c593bc8
> --- /dev/null
> +++ b/src/egl/drivers/dri2/dri2_shared.h
> @@ -0,0 +1,64 @@
> +/*
> + * 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 at bitplanet.net>
> + */
> +
> +#ifndef DRI2_SHARED_INCLUDED
> +#define DRI2_SHARED_INCLUDED
> +
> +#include "egl_dri2.h"
> +
> +EGLBoolean
> +dri2_create_screen(_EGLDisplay *disp);
> +
> +__DRIimage *
> +dri2_lookup_egl_image(__DRIscreen *screen, void *image, void *data);
> +
> +_EGLImage *
> +dri2_create_image_khr_renderbuffer(_EGLDisplay *disp, _EGLContext *ctx,
> + EGLClientBuffer buffer,
> + const EGLint *attr_list);
> +_EGLImage *
> +dri2_create_image_mesa_drm_buffer(_EGLDisplay *disp, _EGLContext *ctx,
> + EGLClientBuffer buffer, const EGLint *attr_list);
> +
> +_EGLImage *
> +dri2_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
> + _EGLContext *ctx, EGLenum target,
> + EGLClientBuffer buffer, const EGLint *attr_list);
> +
> +EGLBoolean
> +dri2_destroy_image_khr(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *image);
> +
> +_EGLImage *
> +dri2_create_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp,
> + const EGLint *attr_list);
> +
> +EGLBoolean
> +dri2_export_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *img,
> + EGLint *name, EGLint *handle, EGLint *stride);
> +
> +#endif
> +
> diff --git a/src/egl/drivers/dri2/drm_dri2.c b/src/egl/drivers/dri2/drm_dri2.c
> new file mode 100644
> index 0000000..9026b64
> --- /dev/null
> +++ b/src/egl/drivers/dri2/drm_dri2.c
> @@ -0,0 +1,250 @@
> +/*
> + * 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 at bitplanet.net>
> + */
> +
> +#ifdef HAVE_LIBUDEV
> +
> +#include <libudev.h>
> +#include "dri2_shared.h"
> +
> +static const __DRIuseInvalidateExtension use_invalidate = {
> + { __DRI_USE_INVALIDATE, 1 }
> +};
> +
> +extern const __DRIimageLookupExtension image_lookup_extension;
> +extern struct dri2_extension_match dri2_driver_extensions[];
> +extern struct dri2_extension_match dri2_core_extensions[];
> +
> +struct dri2_driver_map {
> + int vendor_id;
> + const char *driver;
> + const int *chip_ids;
> + int num_chips_ids;
> +};
> +
> +const int i915_chip_ids[] = {
> + 0x3577, /* PCI_CHIP_I830_M */
> + 0x2562, /* PCI_CHIP_845_G */
> + 0x3582, /* PCI_CHIP_I855_GM */
> + 0x2572, /* PCI_CHIP_I865_G */
> + 0x2582, /* PCI_CHIP_I915_G */
> + 0x258a, /* PCI_CHIP_E7221_G */
> + 0x2592, /* PCI_CHIP_I915_GM */
> + 0x2772, /* PCI_CHIP_I945_G */
> + 0x27a2, /* PCI_CHIP_I945_GM */
> + 0x27ae, /* PCI_CHIP_I945_GME */
> + 0x29b2, /* PCI_CHIP_Q35_G */
> + 0x29c2, /* PCI_CHIP_G33_G */
> + 0x29d2, /* PCI_CHIP_Q33_G */
> + 0xa001, /* PCI_CHIP_IGD_G */
> + 0xa011, /* Pineview */
> +};
> +
> +const int i965_chip_ids[] = {
> + 0x0042, /* PCI_CHIP_ILD_G */
> + 0x0046, /* PCI_CHIP_ILM_G */
> + 0x0102, /* PCI_CHIP_SANDYBRIDGE_GT1 */
> + 0x0106, /* PCI_CHIP_SANDYBRIDGE_M_GT1 */
> + 0x010a, /* PCI_CHIP_SANDYBRIDGE_S */
> + 0x0112, /* PCI_CHIP_SANDYBRIDGE_GT2 */
> + 0x0116, /* PCI_CHIP_SANDYBRIDGE_M_GT2 */
> + 0x0122, /* PCI_CHIP_SANDYBRIDGE_GT2_PLUS */
> + 0x0126, /* PCI_CHIP_SANDYBRIDGE_M_GT2_PLUS */
> + 0x29a2, /* PCI_CHIP_I965_G */
> + 0x2992, /* PCI_CHIP_I965_Q */
> + 0x2982, /* PCI_CHIP_I965_G_1 */
> + 0x2972, /* PCI_CHIP_I946_GZ */
> + 0x2a02, /* PCI_CHIP_I965_GM */
> + 0x2a12, /* PCI_CHIP_I965_GME */
> + 0x2a42, /* PCI_CHIP_GM45_GM */
> + 0x2e02, /* PCI_CHIP_IGD_E_G */
> + 0x2e12, /* PCI_CHIP_Q45_G */
> + 0x2e22, /* PCI_CHIP_G45_G */
> + 0x2e32, /* PCI_CHIP_G41_G */
> + 0x2e42, /* PCI_CHIP_B43_G */
> + 0x2e92, /* PCI_CHIP_B43_G1 */
> +};
> +
> +const struct dri2_driver_map driver_map[] = {
> + { 0x8086, "i915", i915_chip_ids, ARRAY_SIZE(i915_chip_ids) },
> + { 0x8086, "i965", i965_chip_ids, ARRAY_SIZE(i965_chip_ids) },
> +};
> +
> +static char *
> +dri2_get_driver_for_fd(int fd)
> +{
> + struct udev *udev;
> + struct udev_device *device, *parent;
> + struct stat buf;
> + const char *pci_id;
> + char *driver = NULL;
> + int vendor_id, chip_id, i, j;
> +
> + udev = udev_new();
> + if (fstat(fd, &buf) < 0) {
> + _eglLog(_EGL_WARNING, "EGL-DRI2: failed to stat fd %d", fd);
> + goto out;
> + }
> +
> + device = udev_device_new_from_devnum(udev, 'c', buf.st_rdev);
> + if (device == NULL) {
> + _eglLog(_EGL_WARNING,
> + "EGL-DRI2: could not create udev device for fd %d", fd);
> + goto out;
> + }
> +
> + parent = udev_device_get_parent(device);
> + if (parent == NULL) {
> + _eglLog(_EGL_WARNING, "DRI2: could not get parent device");
> + goto out;
> + }
> +
> + pci_id = udev_device_get_property_value(parent, "PCI_ID");
> + if (pci_id == NULL || sscanf(pci_id, "%x:%x", &vendor_id, &chip_id) != 2) {
> + _eglLog(_EGL_WARNING, "EGL-DRI2: malformed or no PCI ID");
> + goto out;
> + }
> +
> + for (i = 0; i < ARRAY_SIZE(driver_map); i++) {
> + if (vendor_id != driver_map[i].vendor_id)
> + continue;
> + for (j = 0; j < driver_map[i].num_chips_ids; j++)
> + if (driver_map[i].chip_ids[j] == chip_id) {
> + driver = strdup(driver_map[i].driver);
> + _eglLog(_EGL_DEBUG, "pci id for %d: %04x:%04x, driver %s",
> + fd, vendor_id, chip_id, driver);
> + goto out;
> + }
> + }
> +
> + out:
> + udev_device_unref(device);
> + udev_unref(udev);
> +
> + return driver;
> +}
> +
> +/**
> + * Called via eglTerminate(), drv->API.Terminate().
> + */
> +static EGLBoolean
> +dri2_drm_dri2_terminate(_EGLDriver *drv, _EGLDisplay *disp)
> +{
> + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
> +
> + _eglReleaseDisplayResources(drv, disp);
> + _eglCleanupDisplay(disp);
> +
> + dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
> + close(dri2_dpy->fd);
> + dlclose(dri2_dpy->driver);
> + free(dri2_dpy);
> + disp->DriverData = NULL;
> +
> + return EGL_TRUE;
> +}
> +
> +static void
> +dri2_drm_initialize_driver(_EGLDriver *drv)
> +{
> + struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
> +
> + dri2_drv->base.API.Terminate = dri2_drm_dri2_terminate;
> + dri2_drv->base.API.CreateImageKHR = dri2_create_image_khr;
> + dri2_drv->base.API.DestroyImageKHR = dri2_destroy_image_khr;
> + dri2_drv->base.API.CreateDRMImageMESA = dri2_create_drm_image_mesa;
> + dri2_drv->base.API.ExportDRMImageMESA = dri2_export_drm_image_mesa;
> +
> +/**
> + * Currently un-supported functions:
> + * CreateWindowSurface, CreatePixmapSurface, CreatePbufferSurface, DestroySurface
> + * SwapBuffers, SwapBuffersRegionNOK, CopyBuffers
> +*/
> +
> + dri2_drv->base.Name = "DRI2_DRM";
> +}
> +
> +EGLBoolean
> +dri2_initialize_drm(_EGLDriver *drv, _EGLDisplay *disp,
> + EGLint *major, EGLint *minor)
> +{
> + struct dri2_egl_display *dri2_dpy;
> + const __DRIextension **extensions;
> + int i;
> +
> + dri2_dpy = malloc(sizeof *dri2_dpy);
> + if (!dri2_dpy)
> + return _eglError(EGL_BAD_ALLOC, "eglInitialize");
> +
> + memset(dri2_dpy, 0, sizeof *dri2_dpy);
> +
> + disp->DriverData = (void *) dri2_dpy;
> + dri2_dpy->fd = (int) disp->PlatformDisplay;
> +
> + dri2_dpy->driver_name = dri2_get_driver_for_fd(dri2_dpy->fd);
> + if (dri2_dpy->driver_name == NULL)
> + return _eglError(EGL_BAD_ALLOC, "DRI2: failed to get driver name");
> +
> + extensions = dri2_load_driver(disp);
> + if (extensions == NULL)
> + goto cleanup_driver_name;
> +
> + if (!dri2_bind_extensions(dri2_dpy, dri2_driver_extensions, extensions)) {
> + goto cleanup_driver;
> + }
> +
> + dri2_dpy->extensions[0] = &image_lookup_extension.base;
> + dri2_dpy->extensions[1] = &use_invalidate.base;
> + dri2_dpy->extensions[2] = NULL;
> +
> + if (!dri2_create_screen(disp))
> + goto cleanup_driver;
> +
> + for (i = 0; dri2_dpy->driver_configs[i]; i++)
> + dri2_add_config(disp, dri2_dpy->driver_configs[i], i + 1, 0, 0, 1);
> +
> + disp->Extensions.MESA_drm_image = EGL_TRUE;
> + disp->Extensions.KHR_image_base = EGL_TRUE;
> + disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE;
> + disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE;
> +
> + /* we're supporting EGL 1.4 */
> + *major = 1;
> + *minor = 4;
> +
> + dri2_drm_initialize_driver(drv);
> +
> + return EGL_TRUE;
> +
> + cleanup_driver:
> + dlclose(dri2_dpy->driver);
> + cleanup_driver_name:
> + free(dri2_dpy->driver_name);
> +
> + return EGL_FALSE;
> +}
> +
> +#endif
> diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
> index dd0cc30..966218d 100644
> --- a/src/egl/drivers/dri2/egl_dri2.c
> +++ b/src/egl/drivers/dri2/egl_dri2.c
> @@ -25,106 +25,115 @@
> * Kristian Høgsberg <krh at bitplanet.net>
> */
>
> -#include <stdlib.h>
> -#include <string.h>
> -#include <stdio.h>
> -#include <limits.h>
> -#include <dlfcn.h>
> -#include <fcntl.h>
> -#include <errno.h>
> -#include <unistd.h>
> -#include <xf86drm.h>
> -#include <GL/gl.h>
> -#include <GL/internal/dri_interface.h>
> -#include <xcb/xcb.h>
> -#include <xcb/dri2.h>
> -#include <xcb/xfixes.h>
> -#include <X11/Xlib-xcb.h>
> -#include <sys/types.h>
> -#include <sys/stat.h>
> +#include "egl_dri2.h"
>
> -#ifdef HAVE_LIBUDEV
> -#include <libudev.h>
> -#endif
> +static const char dri_driver_path[] = DEFAULT_DRIVER_DIR;
> +
> +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;
>
> -#include <glapi/glapi.h>
> -#include "eglconfig.h"
> -#include "eglcontext.h"
> -#include "egldisplay.h"
> -#include "egldriver.h"
> -#include "eglcurrent.h"
> -#include "egllog.h"
> -#include "eglsurface.h"
> -#include "eglimage.h"
> + 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;
> + }
> + }
>
> -#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
> + return ret;
> +}
>
> -struct dri2_egl_driver
> +char *
> +dri2_strndup(const char *s, int length)
> {
> - _EGLDriver base;
> + char *d;
>
> - void (*glFlush)(void);
> -};
> + d = malloc(length + 1);
> + if (d == NULL)
> + return NULL;
>
> -struct dri2_egl_display
> -{
> - xcb_connection_t *conn;
> - int dri2_major;
> - int dri2_minor;
> - __DRIscreen *dri_screen;
> - const __DRIconfig **driver_configs;
> - void *driver;
> - __DRIcoreExtension *core;
> - __DRIdri2Extension *dri2;
> - __DRI2flushExtension *flush;
> - __DRItexBufferExtension *tex_buffer;
> - __DRIimageExtension *image;
> - int fd;
> -
> - char *device_name;
> - char *driver_name;
> -
> - __DRIdri2LoaderExtension loader_extension;
> - const __DRIextension *extensions[3];
> -};
> + memcpy(d, s, length);
> + d[length] = '\0';
>
> -struct dri2_egl_context
> -{
> - _EGLContext base;
> - __DRIcontext *dri_context;
> -};
> + return d;
> +}
>
> -struct dri2_egl_surface
> +const __DRIextension **
> +dri2_load_driver(_EGLDisplay *disp)
> {
> - _EGLSurface base;
> - __DRIdrawable *dri_drawable;
> - xcb_drawable_t drawable;
> - __DRIbuffer buffers[5];
> - int buffer_count;
> - xcb_xfixes_region_t region;
> - int have_fake_front;
> - int swap_interval;
> -};
> + struct dri2_egl_display *dri2_dpy = disp->DriverData;
> + char path[PATH_MAX], *search_paths, *p, *next, *end;
> + const __DRIextension **extensions;
>
> -struct dri2_egl_config
> -{
> - _EGLConfig base;
> - const __DRIconfig *dri_config;
> -};
> + 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;
>
> -struct dri2_egl_image
> -{
> - _EGLImage base;
> - __DRIimage *dri_image;
> -};
> + dri2_dpy->driver = NULL;
> + end = search_paths + strlen(search_paths);
> + for (p = search_paths; p < end && dri2_dpy->driver == NULL; p = next + 1) {
> + int len;
> + next = strchr(p, ':');
> + if (next == NULL)
> + next = end;
>
> -/* standard typecasts */
> -_EGL_DRIVER_STANDARD_TYPECASTS(dri2_egl)
> -_EGL_DRIVER_TYPECAST(dri2_egl_image, _EGLImage, obj)
> + len = next - p;
> +#if GLX_USE_TLS
> + snprintf(path, sizeof path,
> + "%.*s/tls/%s_dri.so", len, p, dri2_dpy->driver_name);
> + dri2_dpy->driver = dlopen(path, RTLD_NOW | RTLD_GLOBAL);
> +#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());
> + }
> + }
>
> -static const __DRIuseInvalidateExtension use_invalidate = {
> - { __DRI_USE_INVALIDATE, 1 }
> -};
> + if (dri2_dpy->driver == NULL) {
> + _eglLog(_EGL_WARNING,
> + "DRI2: failed to open any driver (search paths %s)",
> + search_paths);
> + return NULL;
> + }
> +
> + _eglLog(_EGL_DEBUG, "DRI2: dlopen(%s)", path);
> +
> + extensions = dlsym(dri2_dpy->driver, __DRI_DRIVER_EXTENSIONS);
> + if (extensions == NULL) {
> + _eglLog(_EGL_WARNING,
> + "DRI2: driver exports no extensions (%s)", dlerror());
> + dlclose(dri2_dpy->driver);
> + return NULL;
> + }
> +
> + return extensions;
> +}
>
> EGLint dri2_to_egl_attribute_map[] = {
> 0,
> @@ -177,9 +186,9 @@ EGLint dri2_to_egl_attribute_map[] = {
> EGL_Y_INVERTED_NOK, /* __DRI_ATTRIB_YINVERTED */
> };
>
> -static struct dri2_egl_config *
> +struct dri2_egl_config *
> dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id,
> - int depth, EGLint surface_type)
> + int depth, EGLint surface_type, int accel)
> {
> struct dri2_egl_config *conf;
> struct dri2_egl_display *dri2_dpy;
> @@ -199,53 +208,55 @@ dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id,
> 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
> - /* not valid */;
> - _eglSetConfigKey(&base, EGL_COLOR_BUFFER_TYPE, value);
> - break;
> + if (value & __DRI_ATTRIB_RGBA_BIT)
> + value = EGL_RGB_BUFFER;
> + else if (value & __DRI_ATTRIB_LUMINANCE_BIT)
> + value = EGL_LUMINANCE_BUFFER;
> + else
> + /* not valid */;
> + _eglSetConfigKey(&base, EGL_COLOR_BUFFER_TYPE, value);
> + 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;
> - _eglSetConfigKey(&base, EGL_CONFIG_CAVEAT, value);
> + else
> + value = EGL_NONE;
> + _eglSetConfigKey(&base, EGL_CONFIG_CAVEAT, value);
> break;
>
> case __DRI_ATTRIB_BIND_TO_TEXTURE_RGB:
> - bind_to_texture_rgb = value;
> - break;
> + bind_to_texture_rgb = value;
> + break;
>
> case __DRI_ATTRIB_BIND_TO_TEXTURE_RGBA:
> - bind_to_texture_rgba = value;
> - break;
> + bind_to_texture_rgba = value;
> + break;
>
> case __DRI_ATTRIB_DOUBLE_BUFFER:
> - double_buffer = value;
> - break;
> + double_buffer = value;
> + break;
>
> default:
> - key = dri2_to_egl_attribute_map[attrib];
> - if (key != 0)
> - _eglSetConfigKey(&base, key, value);
> - break;
> + key = dri2_to_egl_attribute_map[attrib];
> + if (key != 0)
> + _eglSetConfigKey(&base, key, value);
> + break;
> }
> }
>
> - /* In EGL, double buffer or not isn't a config attribute. Pixmaps
> + /* In EGL, for DRI2, double buffer or not isn't a config attribute. Pixmaps
> * surfaces are always single buffered, pbuffer surfaces are always
> * back buffers and windows can be either, selected by passing an
> * attribute at window surface construction time. To support this
> * we ignore all double buffer configs and manipulate the buffer we
> - * return in the getBuffer callback to get the behaviour we want. */
> + * return in the getBuffer callback to get the behaviour we want.
> + * for swrast, windows, pixmaps and pbuffers are all double buffered */
>
> - if (double_buffer)
> + if ((double_buffer && accel) ||
> + (!double_buffer && !accel))
> return NULL;
>
> if (depth > 0 && depth != _eglGetConfigKey(&base, EGL_BUFFER_SIZE))
> @@ -257,783 +268,34 @@ dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id,
> if (surface_type & (EGL_PIXMAP_BIT | EGL_PBUFFER_BIT)) {
> _eglSetConfigKey(&base, EGL_BIND_TO_TEXTURE_RGB, bind_to_texture_rgb);
> if (_eglGetConfigKey(&base, EGL_ALPHA_SIZE) > 0)
> - _eglSetConfigKey(&base,
> - EGL_BIND_TO_TEXTURE_RGBA, bind_to_texture_rgba);
> + _eglSetConfigKey(&base,
> + EGL_BIND_TO_TEXTURE_RGBA, bind_to_texture_rgba);
> }
>
> _eglSetConfigKey(&base, EGL_RENDERABLE_TYPE, disp->ClientAPIsMask);
> _eglSetConfigKey(&base, EGL_CONFORMANT, disp->ClientAPIsMask);
>
> if (!_eglValidateConfig(&base, EGL_FALSE)) {
> - _eglLog(_EGL_DEBUG, "DRI2: failed to validate config %d", id);
> - return NULL;
> - }
> -
> - conf = malloc(sizeof *conf);
> - if (conf != NULL) {
> - memcpy(&conf->base, &base, sizeof base);
> - conf->dri_config = dri_config;
> - _eglAddConfig(disp, &conf->base);
> - }
> -
> - return conf;
> -}
> -
> -/**
> - * Process list of buffer received from the server
> - *
> - * Processes the list of buffers received in a reply from the server to either
> - * \c DRI2GetBuffers or \c DRI2GetBuffersWithFormat.
> - */
> -static void
> -dri2_process_buffers(struct dri2_egl_surface *dri2_surf,
> - xcb_dri2_dri2_buffer_t *buffers, unsigned count)
> -{
> - struct dri2_egl_display *dri2_dpy =
> - dri2_egl_display(dri2_surf->base.Resource.Display);
> - xcb_rectangle_t rectangle;
> - int i;
> -
> - dri2_surf->buffer_count = count;
> - dri2_surf->have_fake_front = 0;
> -
> - /* This assumes the DRI2 buffer attachment tokens matches the
> - * __DRIbuffer tokens. */
> - for (i = 0; i < count; i++) {
> - dri2_surf->buffers[i].attachment = buffers[i].attachment;
> - dri2_surf->buffers[i].name = buffers[i].name;
> - dri2_surf->buffers[i].pitch = buffers[i].pitch;
> - dri2_surf->buffers[i].cpp = buffers[i].cpp;
> - dri2_surf->buffers[i].flags = buffers[i].flags;
> -
> - /* We only use the DRI drivers single buffer configs. This
> - * means that if we try to render to a window, DRI2 will give us
> - * the fake front buffer, which we'll use as a back buffer.
> - * Note that EGL doesn't require that several clients rendering
> - * to the same window must see the same aux buffers. */
> - if (dri2_surf->buffers[i].attachment == __DRI_BUFFER_FAKE_FRONT_LEFT)
> - dri2_surf->have_fake_front = 1;
> - }
> -
> - if (dri2_surf->region != XCB_NONE)
> - xcb_xfixes_destroy_region(dri2_dpy->conn, dri2_surf->region);
> -
> - rectangle.x = 0;
> - rectangle.y = 0;
> - rectangle.width = dri2_surf->base.Width;
> - rectangle.height = dri2_surf->base.Height;
> - dri2_surf->region = xcb_generate_id(dri2_dpy->conn);
> - xcb_xfixes_create_region(dri2_dpy->conn, dri2_surf->region, 1, &rectangle);
> -}
> -
> -static __DRIbuffer *
> -dri2_get_buffers(__DRIdrawable * driDrawable,
> - int *width, int *height,
> - unsigned int *attachments, int count,
> - int *out_count, void *loaderPrivate)
> -{
> - struct dri2_egl_surface *dri2_surf = loaderPrivate;
> - struct dri2_egl_display *dri2_dpy =
> - dri2_egl_display(dri2_surf->base.Resource.Display);
> - xcb_dri2_dri2_buffer_t *buffers;
> - xcb_dri2_get_buffers_reply_t *reply;
> - xcb_dri2_get_buffers_cookie_t cookie;
> -
> - cookie = xcb_dri2_get_buffers_unchecked (dri2_dpy->conn,
> - dri2_surf->drawable,
> - count, count, attachments);
> - reply = xcb_dri2_get_buffers_reply (dri2_dpy->conn, cookie, NULL);
> - buffers = xcb_dri2_get_buffers_buffers (reply);
> - if (buffers == NULL)
> - return NULL;
> -
> - *out_count = reply->count;
> - dri2_surf->base.Width = *width = reply->width;
> - dri2_surf->base.Height = *height = reply->height;
> - dri2_process_buffers(dri2_surf, buffers, *out_count);
> -
> - free(reply);
> -
> - return dri2_surf->buffers;
> -}
> -
> -static void
> -dri2_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate)
> -{
> - /* FIXME: Does EGL support front buffer rendering at all? */
> -
> -#if 0
> - struct dri2_egl_surface *dri2_surf = loaderPrivate;
> -
> - dri2WaitGL(dri2_surf);
> -#endif
> -}
> -
> -static __DRIimage *
> -dri2_lookup_egl_image(__DRIscreen *screen, void *image, void *data)
> -{
> - _EGLDisplay *disp = data;
> - struct dri2_egl_image *dri2_img;
> - _EGLImage *img;
> -
> - 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;
> -}
> -
> -static const __DRIimageLookupExtension image_lookup_extension = {
> - { __DRI_IMAGE_LOOKUP, 1 },
> - dri2_lookup_egl_image
> -};
> -
> -static __DRIbuffer *
> -dri2_get_buffers_with_format(__DRIdrawable * driDrawable,
> - int *width, int *height,
> - unsigned int *attachments, int count,
> - int *out_count, void *loaderPrivate)
> -{
> - struct dri2_egl_surface *dri2_surf = loaderPrivate;
> - struct dri2_egl_display *dri2_dpy =
> - dri2_egl_display(dri2_surf->base.Resource.Display);
> - xcb_dri2_dri2_buffer_t *buffers;
> - xcb_dri2_get_buffers_with_format_reply_t *reply;
> - xcb_dri2_get_buffers_with_format_cookie_t cookie;
> - xcb_dri2_attach_format_t *format_attachments;
> -
> - format_attachments = (xcb_dri2_attach_format_t *) attachments;
> - cookie = xcb_dri2_get_buffers_with_format_unchecked (dri2_dpy->conn,
> - dri2_surf->drawable,
> - count, count,
> - format_attachments);
> -
> - reply = xcb_dri2_get_buffers_with_format_reply (dri2_dpy->conn,
> - cookie, NULL);
> - if (reply == NULL)
> - return NULL;
> -
> - buffers = xcb_dri2_get_buffers_with_format_buffers (reply);
> - dri2_surf->base.Width = *width = reply->width;
> - dri2_surf->base.Height = *height = reply->height;
> - *out_count = reply->count;
> - dri2_process_buffers(dri2_surf, buffers, *out_count);
> -
> - free(reply);
> -
> - return dri2_surf->buffers;
> -}
> -
> -static const char dri_driver_path[] = DEFAULT_DRIVER_DIR;
> -
> -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) },
> - { __DRI_DRI2, 1, offsetof(struct dri2_egl_display, dri2) },
> - { NULL }
> -};
> -
> -static struct dri2_extension_match dri2_core_extensions[] = {
> - { __DRI2_FLUSH, 1, offsetof(struct dri2_egl_display, flush) },
> - { __DRI_TEX_BUFFER, 2, offsetof(struct dri2_egl_display, tex_buffer) },
> - { __DRI_IMAGE, 1, offsetof(struct dri2_egl_display, image) },
> - { NULL }
> -};
> -
> -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;
> -}
> -
> -static char *
> -dri2_strndup(const char *s, int length)
> -{
> - char *d;
> -
> - d = malloc(length + 1);
> - if (d == NULL)
> - return NULL;
> -
> - memcpy(d, s, length);
> - d[length] = '\0';
> -
> - return d;
> -}
> -
> -static EGLBoolean
> -dri2_connect(struct dri2_egl_display *dri2_dpy)
> -{
> - xcb_xfixes_query_version_reply_t *xfixes_query;
> - xcb_xfixes_query_version_cookie_t xfixes_query_cookie;
> - xcb_dri2_query_version_reply_t *dri2_query;
> - xcb_dri2_query_version_cookie_t dri2_query_cookie;
> - xcb_dri2_connect_reply_t *connect;
> - xcb_dri2_connect_cookie_t connect_cookie;
> - xcb_generic_error_t *error;
> - xcb_screen_iterator_t s;
> -
> - xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_xfixes_id);
> - xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_dri2_id);
> -
> - xfixes_query_cookie = xcb_xfixes_query_version(dri2_dpy->conn,
> - XCB_XFIXES_MAJOR_VERSION,
> - XCB_XFIXES_MINOR_VERSION);
> -
> - dri2_query_cookie = xcb_dri2_query_version (dri2_dpy->conn,
> - XCB_DRI2_MAJOR_VERSION,
> - XCB_DRI2_MINOR_VERSION);
> -
> - s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn));
> - connect_cookie = xcb_dri2_connect_unchecked (dri2_dpy->conn,
> - s.data->root,
> - XCB_DRI2_DRIVER_TYPE_DRI);
> -
> - xfixes_query =
> - xcb_xfixes_query_version_reply (dri2_dpy->conn,
> - xfixes_query_cookie, &error);
> - if (xfixes_query == NULL ||
> - error != NULL || xfixes_query->major_version < 2) {
> - _eglLog(_EGL_FATAL, "DRI2: failed to query xfixes version");
> - free(error);
> - return EGL_FALSE;
> - }
> - free(xfixes_query);
> -
> - dri2_query =
> - xcb_dri2_query_version_reply (dri2_dpy->conn, dri2_query_cookie, &error);
> - if (dri2_query == NULL || error != NULL) {
> - _eglLog(_EGL_FATAL, "DRI2: failed to query version");
> - free(error);
> - return EGL_FALSE;
> - }
> - dri2_dpy->dri2_major = dri2_query->major_version;
> - dri2_dpy->dri2_minor = dri2_query->minor_version;
> - free(dri2_query);
> -
> - connect = xcb_dri2_connect_reply (dri2_dpy->conn, connect_cookie, NULL);
> - if (connect == NULL ||
> - connect->driver_name_length + connect->device_name_length == 0) {
> - _eglLog(_EGL_FATAL, "DRI2: failed to authenticate");
> - return EGL_FALSE;
> - }
> -
> - dri2_dpy->device_name =
> - dri2_strndup(xcb_dri2_connect_device_name (connect),
> - xcb_dri2_connect_device_name_length (connect));
> -
> - dri2_dpy->driver_name =
> - dri2_strndup(xcb_dri2_connect_driver_name (connect),
> - xcb_dri2_connect_driver_name_length (connect));
> -
> - if (dri2_dpy->device_name == NULL || dri2_dpy->driver_name == NULL) {
> - free(dri2_dpy->device_name);
> - free(dri2_dpy->driver_name);
> - free(connect);
> - return EGL_FALSE;
> - }
> - free(connect);
> -
> - return EGL_TRUE;
> -}
> -
> -static EGLBoolean
> -dri2_authenticate(struct dri2_egl_display *dri2_dpy)
> -{
> - xcb_dri2_authenticate_reply_t *authenticate;
> - xcb_dri2_authenticate_cookie_t authenticate_cookie;
> - xcb_screen_iterator_t s;
> - drm_magic_t magic;
> -
> - if (drmGetMagic(dri2_dpy->fd, &magic)) {
> - _eglLog(_EGL_FATAL, "DRI2: failed to get drm magic");
> - return EGL_FALSE;
> - }
> -
> - s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn));
> - authenticate_cookie =
> - xcb_dri2_authenticate_unchecked(dri2_dpy->conn, s.data->root, magic);
> - authenticate =
> - xcb_dri2_authenticate_reply(dri2_dpy->conn, authenticate_cookie, NULL);
> - if (authenticate == NULL || !authenticate->authenticated) {
> - _eglLog(_EGL_FATAL, "DRI2: failed to authenticate");
> - free(authenticate);
> - return EGL_FALSE;
> - }
> -
> - free(authenticate);
> -
> - return EGL_TRUE;
> -}
> -
> -static EGLBoolean
> -dri2_add_configs_for_visuals(struct dri2_egl_display *dri2_dpy,
> - _EGLDisplay *disp)
> -{
> - xcb_screen_iterator_t s;
> - xcb_depth_iterator_t d;
> - xcb_visualtype_t *visuals;
> - int i, j, id;
> - struct dri2_egl_config *conf;
> - EGLint surface_type;
> -
> - s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn));
> - d = xcb_screen_allowed_depths_iterator(s.data);
> - id = 1;
> -
> - surface_type =
> - EGL_WINDOW_BIT |
> - EGL_PIXMAP_BIT |
> - EGL_PBUFFER_BIT |
> - EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
> -
> - while (d.rem > 0) {
> - EGLBoolean class_added[6] = { 0, };
> -
> - visuals = xcb_depth_visuals(d.data);
> - for (i = 0; i < xcb_depth_visuals_length(d.data); i++) {
> - if (class_added[visuals[i]._class])
> - continue;
> -
> - class_added[visuals[i]._class] = EGL_TRUE;
> - for (j = 0; dri2_dpy->driver_configs[j]; j++) {
> - conf = dri2_add_config(disp, dri2_dpy->driver_configs[j],
> - id++, d.data->depth, surface_type);
> - if (conf == NULL)
> - continue;
> - _eglSetConfigKey(&conf->base,
> - EGL_NATIVE_VISUAL_ID, visuals[i].visual_id);
> - _eglSetConfigKey(&conf->base,
> - EGL_NATIVE_VISUAL_TYPE, visuals[i]._class);
> - }
> - }
> -
> - xcb_depth_next(&d);
> - }
> -
> - if (!_eglGetArraySize(disp->Configs)) {
> - _eglLog(_EGL_WARNING, "DRI2: failed to create any config");
> - return EGL_FALSE;
> - }
> -
> - return EGL_TRUE;
> -}
> -
> -static EGLBoolean
> -dri2_load_driver(_EGLDisplay *disp)
> -{
> - struct dri2_egl_display *dri2_dpy = disp->DriverData;
> - const __DRIextension **extensions;
> - char path[PATH_MAX], *search_paths, *p, *next, *end;
> -
> - 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) {
> - int len;
> - next = strchr(p, ':');
> - if (next == NULL)
> - next = end;
> -
> - len = next - p;
> -#if GLX_USE_TLS
> - snprintf(path, sizeof path,
> - "%.*s/tls/%s_dri.so", len, p, dri2_dpy->driver_name);
> - dri2_dpy->driver = dlopen(path, RTLD_NOW | RTLD_GLOBAL);
> -#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());
> - }
> - }
> -
> - if (dri2_dpy->driver == NULL) {
> - _eglLog(_EGL_WARNING,
> - "DRI2: failed to open any driver (search paths %s)",
> - search_paths);
> - return EGL_FALSE;
> - }
> -
> - _eglLog(_EGL_DEBUG, "DRI2: dlopen(%s)", path);
> - extensions = dlsym(dri2_dpy->driver, __DRI_DRIVER_EXTENSIONS);
> - if (extensions == NULL) {
> - _eglLog(_EGL_WARNING,
> - "DRI2: driver exports no extensions (%s)", dlerror());
> - dlclose(dri2_dpy->driver);
> - return EGL_FALSE;
> - }
> -
> - if (!dri2_bind_extensions(dri2_dpy, dri2_driver_extensions, extensions)) {
> - dlclose(dri2_dpy->driver);
> - return EGL_FALSE;
> - }
> -
> - return EGL_TRUE;
> -}
> -
> -static EGLBoolean
> -dri2_create_screen(_EGLDisplay *disp)
> -{
> - const __DRIextension **extensions;
> - struct dri2_egl_display *dri2_dpy;
> - unsigned int api_mask;
> -
> - dri2_dpy = disp->DriverData;
> - dri2_dpy->dri_screen =
> - dri2_dpy->dri2->createNewScreen(0, dri2_dpy->fd, dri2_dpy->extensions,
> - &dri2_dpy->driver_configs, disp);
> -
> - if (dri2_dpy->dri_screen == NULL) {
> - _eglLog(_EGL_WARNING, "DRI2: failed to create dri screen");
> - return EGL_FALSE;
> - }
> -
> - extensions = dri2_dpy->core->getExtensions(dri2_dpy->dri_screen);
> - if (!dri2_bind_extensions(dri2_dpy, dri2_core_extensions, extensions))
> - goto cleanup_dri_screen;
> -
> - if (dri2_dpy->dri2->base.version >= 2)
> - api_mask = dri2_dpy->dri2->getAPIMask(dri2_dpy->dri_screen);
> - else
> - api_mask = 1 << __DRI_API_OPENGL;
> -
> - disp->ClientAPIsMask = 0;
> - if (api_mask & (1 <<__DRI_API_OPENGL))
> - disp->ClientAPIsMask |= EGL_OPENGL_BIT;
> - if (api_mask & (1 <<__DRI_API_GLES))
> - disp->ClientAPIsMask |= EGL_OPENGL_ES_BIT;
> - if (api_mask & (1 << __DRI_API_GLES2))
> - disp->ClientAPIsMask |= EGL_OPENGL_ES2_BIT;
> -
> - if (dri2_dpy->dri2->base.version >= 2) {
> - disp->Extensions.KHR_surfaceless_gles1 = EGL_TRUE;
> - disp->Extensions.KHR_surfaceless_gles2 = EGL_TRUE;
> - disp->Extensions.KHR_surfaceless_opengl = EGL_TRUE;
> - }
> -
> - return EGL_TRUE;
> -
> - cleanup_dri_screen:
> - dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
> -
> - return EGL_FALSE;
> -}
> -
> -static EGLBoolean
> -dri2_initialize_x11(_EGLDriver *drv, _EGLDisplay *disp,
> - EGLint *major, EGLint *minor)
> -{
> - struct dri2_egl_display *dri2_dpy;
> -
> - dri2_dpy = malloc(sizeof *dri2_dpy);
> - if (!dri2_dpy)
> - return _eglError(EGL_BAD_ALLOC, "eglInitialize");
> -
> - disp->DriverData = (void *) dri2_dpy;
> - if (disp->PlatformDisplay == NULL) {
> - dri2_dpy->conn = xcb_connect(0, 0);
> - } else {
> - dri2_dpy->conn = XGetXCBConnection((Display *) disp->PlatformDisplay);
> - }
> -
> - if (xcb_connection_has_error(dri2_dpy->conn)) {
> - _eglLog(_EGL_WARNING, "DRI2: xcb_connect failed");
> - goto cleanup_dpy;
> - }
> -
> - if (dri2_dpy->conn) {
> - if (!dri2_connect(dri2_dpy))
> - goto cleanup_conn;
> - }
> -
> - if (!dri2_load_driver(disp))
> - goto cleanup_conn;
> -
> - dri2_dpy->fd = open(dri2_dpy->device_name, O_RDWR);
> - if (dri2_dpy->fd == -1) {
> - _eglLog(_EGL_WARNING,
> - "DRI2: could not open %s (%s)", dri2_dpy->device_name,
> - strerror(errno));
> - goto cleanup_driver;
> - }
> -
> - if (dri2_dpy->conn) {
> - if (!dri2_authenticate(dri2_dpy))
> - goto cleanup_fd;
> - }
> -
> - if (dri2_dpy->dri2_minor >= 1) {
> - dri2_dpy->loader_extension.base.name = __DRI_DRI2_LOADER;
> - dri2_dpy->loader_extension.base.version = 3;
> - dri2_dpy->loader_extension.getBuffers = dri2_get_buffers;
> - dri2_dpy->loader_extension.flushFrontBuffer = dri2_flush_front_buffer;
> - dri2_dpy->loader_extension.getBuffersWithFormat =
> - dri2_get_buffers_with_format;
> - } else {
> - dri2_dpy->loader_extension.base.name = __DRI_DRI2_LOADER;
> - dri2_dpy->loader_extension.base.version = 2;
> - dri2_dpy->loader_extension.getBuffers = dri2_get_buffers;
> - dri2_dpy->loader_extension.flushFrontBuffer = dri2_flush_front_buffer;
> - dri2_dpy->loader_extension.getBuffersWithFormat = NULL;
> - }
> -
> - dri2_dpy->extensions[0] = &dri2_dpy->loader_extension.base;
> - dri2_dpy->extensions[1] = &image_lookup_extension.base;
> - dri2_dpy->extensions[2] = NULL;
> -
> - if (!dri2_create_screen(disp))
> - goto cleanup_fd;
> -
> - if (dri2_dpy->conn) {
> - if (!dri2_add_configs_for_visuals(dri2_dpy, disp))
> - goto cleanup_configs;
> - }
> -
> - disp->Extensions.MESA_drm_image = EGL_TRUE;
> - disp->Extensions.KHR_image_base = EGL_TRUE;
> - disp->Extensions.KHR_image_pixmap = EGL_TRUE;
> - disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE;
> - disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE;
> - disp->Extensions.NOK_swap_region = EGL_TRUE;
> - disp->Extensions.NOK_texture_from_pixmap = EGL_TRUE;
> -
> - /* we're supporting EGL 1.4 */
> - *major = 1;
> - *minor = 4;
> -
> - return EGL_TRUE;
> -
> - cleanup_configs:
> - _eglCleanupDisplay(disp);
> - dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
> - cleanup_fd:
> - close(dri2_dpy->fd);
> - cleanup_driver:
> - dlclose(dri2_dpy->driver);
> - cleanup_conn:
> - if (disp->PlatformDisplay == NULL)
> - xcb_disconnect(dri2_dpy->conn);
> - cleanup_dpy:
> - free(dri2_dpy);
> -
> - return EGL_FALSE;
> -}
> -
> -#ifdef HAVE_LIBUDEV
> -
> -struct dri2_driver_map {
> - int vendor_id;
> - const char *driver;
> - const int *chip_ids;
> - int num_chips_ids;
> -};
> -
> -const int i915_chip_ids[] = {
> - 0x3577, /* PCI_CHIP_I830_M */
> - 0x2562, /* PCI_CHIP_845_G */
> - 0x3582, /* PCI_CHIP_I855_GM */
> - 0x2572, /* PCI_CHIP_I865_G */
> - 0x2582, /* PCI_CHIP_I915_G */
> - 0x258a, /* PCI_CHIP_E7221_G */
> - 0x2592, /* PCI_CHIP_I915_GM */
> - 0x2772, /* PCI_CHIP_I945_G */
> - 0x27a2, /* PCI_CHIP_I945_GM */
> - 0x27ae, /* PCI_CHIP_I945_GME */
> - 0x29b2, /* PCI_CHIP_Q35_G */
> - 0x29c2, /* PCI_CHIP_G33_G */
> - 0x29d2, /* PCI_CHIP_Q33_G */
> - 0xa001, /* PCI_CHIP_IGD_G */
> - 0xa011, /* Pineview */
> -};
> -
> -const int i965_chip_ids[] = {
> - 0x0042, /* PCI_CHIP_ILD_G */
> - 0x0046, /* PCI_CHIP_ILM_G */
> - 0x0102, /* PCI_CHIP_SANDYBRIDGE_GT1 */
> - 0x0106, /* PCI_CHIP_SANDYBRIDGE_M_GT1 */
> - 0x010a, /* PCI_CHIP_SANDYBRIDGE_S */
> - 0x0112, /* PCI_CHIP_SANDYBRIDGE_GT2 */
> - 0x0116, /* PCI_CHIP_SANDYBRIDGE_M_GT2 */
> - 0x0122, /* PCI_CHIP_SANDYBRIDGE_GT2_PLUS */
> - 0x0126, /* PCI_CHIP_SANDYBRIDGE_M_GT2_PLUS */
> - 0x29a2, /* PCI_CHIP_I965_G */
> - 0x2992, /* PCI_CHIP_I965_Q */
> - 0x2982, /* PCI_CHIP_I965_G_1 */
> - 0x2972, /* PCI_CHIP_I946_GZ */
> - 0x2a02, /* PCI_CHIP_I965_GM */
> - 0x2a12, /* PCI_CHIP_I965_GME */
> - 0x2a42, /* PCI_CHIP_GM45_GM */
> - 0x2e02, /* PCI_CHIP_IGD_E_G */
> - 0x2e12, /* PCI_CHIP_Q45_G */
> - 0x2e22, /* PCI_CHIP_G45_G */
> - 0x2e32, /* PCI_CHIP_G41_G */
> - 0x2e42, /* PCI_CHIP_B43_G */
> - 0x2e92, /* PCI_CHIP_B43_G1 */
> -};
> -
> -const struct dri2_driver_map driver_map[] = {
> - { 0x8086, "i915", i915_chip_ids, ARRAY_SIZE(i915_chip_ids) },
> - { 0x8086, "i965", i965_chip_ids, ARRAY_SIZE(i965_chip_ids) },
> -};
> -
> -static char *
> -dri2_get_driver_for_fd(int fd)
> -{
> - struct udev *udev;
> - struct udev_device *device, *parent;
> - struct stat buf;
> - const char *pci_id;
> - char *driver = NULL;
> - int vendor_id, chip_id, i, j;
> -
> - udev = udev_new();
> - if (fstat(fd, &buf) < 0) {
> - _eglLog(_EGL_WARNING, "EGL-DRI2: failed to stat fd %d", fd);
> - goto out;
> - }
> -
> - device = udev_device_new_from_devnum(udev, 'c', buf.st_rdev);
> - if (device == NULL) {
> - _eglLog(_EGL_WARNING,
> - "EGL-DRI2: could not create udev device for fd %d", fd);
> - goto out;
> - }
> -
> - parent = udev_device_get_parent(device);
> - if (parent == NULL) {
> - _eglLog(_EGL_WARNING, "DRI2: could not get parent device");
> - goto out;
> - }
> -
> - pci_id = udev_device_get_property_value(parent, "PCI_ID");
> - if (pci_id == NULL || sscanf(pci_id, "%x:%x", &vendor_id, &chip_id) != 2) {
> - _eglLog(_EGL_WARNING, "EGL-DRI2: malformed or no PCI ID");
> - goto out;
> - }
> -
> - for (i = 0; i < ARRAY_SIZE(driver_map); i++) {
> - if (vendor_id != driver_map[i].vendor_id)
> - continue;
> - for (j = 0; j < driver_map[i].num_chips_ids; j++)
> - if (driver_map[i].chip_ids[j] == chip_id) {
> - driver = strdup(driver_map[i].driver);
> - _eglLog(_EGL_DEBUG, "pci id for %d: %04x:%04x, driver %s",
> - fd, vendor_id, chip_id, driver);
> - goto out;
> - }
> - }
> -
> - out:
> - udev_device_unref(device);
> - udev_unref(udev);
> -
> - return driver;
> -}
> -
> -static EGLBoolean
> -dri2_initialize_drm(_EGLDriver *drv, _EGLDisplay *disp,
> - EGLint *major, EGLint *minor)
> -{
> - struct dri2_egl_display *dri2_dpy;
> - int i;
> -
> - dri2_dpy = malloc(sizeof *dri2_dpy);
> - if (!dri2_dpy)
> - return _eglError(EGL_BAD_ALLOC, "eglInitialize");
> -
> - disp->DriverData = (void *) dri2_dpy;
> - dri2_dpy->fd = (int) disp->PlatformDisplay;
> -
> - dri2_dpy->driver_name = dri2_get_driver_for_fd(dri2_dpy->fd);
> - if (dri2_dpy->driver_name == NULL)
> - return _eglError(EGL_BAD_ALLOC, "DRI2: failed to get driver name");
> -
> - if (!dri2_load_driver(disp))
> - goto cleanup_driver_name;
> -
> - dri2_dpy->extensions[0] = &image_lookup_extension.base;
> - dri2_dpy->extensions[1] = &use_invalidate.base;
> - dri2_dpy->extensions[2] = NULL;
> -
> - if (!dri2_create_screen(disp))
> - goto cleanup_driver;
> -
> - for (i = 0; dri2_dpy->driver_configs[i]; i++)
> - dri2_add_config(disp, dri2_dpy->driver_configs[i], i + 1, 0, 0);
> -
> - disp->Extensions.MESA_drm_image = EGL_TRUE;
> - disp->Extensions.KHR_image_base = EGL_TRUE;
> - disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE;
> - disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE;
> -
> - /* we're supporting EGL 1.4 */
> - *major = 1;
> - *minor = 4;
> -
> - return EGL_TRUE;
> + _eglLog(_EGL_DEBUG, "DRI2: failed to validate config %d", id);
> + return NULL;
> + }
>
> - cleanup_driver:
> - dlclose(dri2_dpy->driver);
> - cleanup_driver_name:
> - free(dri2_dpy->driver_name);
> + conf = malloc(sizeof *conf);
> + if (conf != NULL) {
> + memcpy(&conf->base, &base, sizeof base);
> + conf->dri_config = dri_config;
> + _eglAddConfig(disp, &conf->base);
> + }
>
> - return EGL_FALSE;
> + return conf;
> }
>
> -#endif
> -
> /**
> * Called via eglInitialize(), GLX_drv->API.Initialize().
> */
> static EGLBoolean
> dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp,
> - EGLint *major, EGLint *minor)
> + EGLint *major, EGLint *minor)
> {
> switch (disp->Platform) {
> case _EGL_PLATFORM_X11:
> @@ -1050,34 +312,11 @@ dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp,
> }
>
> /**
> - * 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);
> -
> - dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
> - close(dri2_dpy->fd);
> - dlclose(dri2_dpy->driver);
> - if (disp->PlatformDisplay == NULL)
> - xcb_disconnect(dri2_dpy->conn);
> - free(dri2_dpy);
> - disp->DriverData = NULL;
> -
> - return EGL_TRUE;
> -}
> -
> -
> -/**
> * Called via eglCreateContext(), drv->API.CreateContext().
> */
> static _EGLContext *
> dri2_create_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
> - _EGLContext *share_list, const EGLint *attrib_list)
> + _EGLContext *share_list, const EGLint *attrib_list)
> {
> struct dri2_egl_context *dri2_ctx;
> struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
> @@ -1105,8 +344,8 @@ dri2_create_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
> api = __DRI_API_GLES2;
> break;
> default:
> - _eglError(EGL_BAD_PARAMETER, "eglCreateContext");
> - return NULL;
> + _eglError(EGL_BAD_PARAMETER, "eglCreateContext");
> + return NULL;
> }
> break;
> case EGL_OPENGL_API:
> @@ -1122,21 +361,45 @@ dri2_create_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
> else
> dri_config = NULL;
>
> - if (dri2_dpy->dri2->base.version >= 2) {
> - dri2_ctx->dri_context =
> - dri2_dpy->dri2->createNewContextForAPI(dri2_dpy->dri_screen,
> - api,
> - dri_config,
> - dri2_ctx_shared ?
> - dri2_ctx_shared->dri_context : NULL,
> - dri2_ctx);
> - } else if (api == __DRI_API_OPENGL) {
> - dri2_ctx->dri_context =
> - dri2_dpy->dri2->createNewContext(dri2_dpy->dri_screen,
> - dri2_config->dri_config,
> - dri2_ctx_shared ?
> - dri2_ctx_shared->dri_context : NULL,
> - dri2_ctx);
> + if (dri2_dpy->dri2) {
> + if (dri2_dpy->dri2->base.version >= 2) {
> + dri2_ctx->dri_context =
> + dri2_dpy->dri2->createNewContextForAPI(dri2_dpy->dri_screen,
> + api,
> + dri_config,
> + dri2_ctx_shared ?
> + dri2_ctx_shared->dri_context : NULL,
> + dri2_ctx);
> +
> + } else if (api == __DRI_API_OPENGL) {
> + dri2_ctx->dri_context =
> + dri2_dpy->dri2->createNewContext(dri2_dpy->dri_screen,
> + dri_config,
> + dri2_ctx_shared ?
> + dri2_ctx_shared->dri_context : NULL,
> + dri2_ctx);
> + } else {
> + /* fail */
> + }
> + } else if (dri2_dpy->swrast) {
> + if (dri2_dpy->swrast->base.version >= 2) {
> + dri2_ctx->dri_context =
> + dri2_dpy->swrast->createNewContextForAPI(dri2_dpy->dri_screen,
> + api,
> + dri_config,
> + dri2_ctx_shared ?
> + dri2_ctx_shared->dri_context : NULL,
> + dri2_ctx);
> + } else if (api == __DRI_API_OPENGL) {
> + dri2_ctx->dri_context =
> + dri2_dpy->core->createNewContext(dri2_dpy->dri_screen,
> + dri_config,
> + dri2_ctx_shared ?
> + dri2_ctx_shared->dri_context : NULL,
> + dri2_ctx);
> + } else {
> + /* fail */
> + }
> } else {
> /* fail */
> }
> @@ -1151,33 +414,43 @@ dri2_create_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
> return NULL;
> }
>
> +#if 0
> static EGLBoolean
> dri2_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
> {
> struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
> struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
>
> + _eglLog(_EGL_WARNING, "Destroy 1");
> +
> if (_eglIsSurfaceBound(surf))
> return EGL_TRUE;
>
> (*dri2_dpy->core->destroyDrawable)(dri2_surf->dri_drawable);
> -
> - xcb_dri2_destroy_drawable (dri2_dpy->conn, dri2_surf->drawable);
> +
> + dri2_dpy->destroyDrawable(dri2_dpy, dri2_surf);
> +#if 0
> + if (dri2_dpy->x11_dri2_accel) {
> + xcb_dri2_destroy_drawable (dri2_dpy->conn, dri2_surf->drawable);
> + } else {
> + swrastDestroySurface(dri2_surf, dri2_dpy);
> + }
>
> if (surf->Type == EGL_PBUFFER_BIT)
> xcb_free_pixmap (dri2_dpy->conn, dri2_surf->drawable);
>
> free(surf);
> -
> +#endif
> return EGL_TRUE;
> }
> +#endif
>
> /**
> * Called via eglMakeCurrent(), drv->API.MakeCurrent().
> */
> static EGLBoolean
> dri2_make_current(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf,
> - _EGLSurface *rsurf, _EGLContext *ctx)
> + _EGLSurface *rsurf, _EGLContext *ctx)
> {
> struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
> struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
> @@ -1202,11 +475,13 @@ dri2_make_current(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf,
> if ((cctx == NULL && ddraw == NULL && rdraw == NULL) ||
> dri2_dpy->core->bindContext(cctx, ddraw, rdraw)) {
> if (dsurf && !_eglIsSurfaceLinked(dsurf))
> - dri2_destroy_surface(drv, disp, dsurf);
> + if (dri2_drv->base.API.DestroySurface)
> + dri2_drv->base.API.DestroySurface(drv, disp, dsurf);
> if (rsurf && rsurf != dsurf && !_eglIsSurfaceLinked(dsurf))
> - dri2_destroy_surface(drv, disp, rsurf);
> + if (dri2_drv->base.API.DestroySurface)
> + dri2_drv->base.API.DestroySurface(drv, disp, rsurf);
> if (ctx != NULL && !_eglIsContextLinked(ctx))
> - dri2_dpy->core->unbindContext(dri2_egl_context(ctx)->dri_context);
> + dri2_dpy->core->unbindContext(dri2_egl_context(ctx)->dri_context);
>
> return EGL_TRUE;
> } else {
> @@ -1216,189 +491,6 @@ dri2_make_current(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf,
> }
> }
>
> -/**
> - * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
> - */
> -static _EGLSurface *
> -dri2_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
> - _EGLConfig *conf, EGLNativeWindowType window,
> - const EGLint *attrib_list)
> -{
> - struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
> - struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
> - struct dri2_egl_surface *dri2_surf;
> - xcb_get_geometry_cookie_t cookie;
> - xcb_get_geometry_reply_t *reply;
> - xcb_screen_iterator_t s;
> - xcb_generic_error_t *error;
> -
> - dri2_surf = malloc(sizeof *dri2_surf);
> - if (!dri2_surf) {
> - _eglError(EGL_BAD_ALLOC, "dri2_create_surface");
> - return NULL;
> - }
> -
> - if (!_eglInitSurface(&dri2_surf->base, disp, type, conf, attrib_list))
> - goto cleanup_surf;
> -
> - dri2_surf->region = XCB_NONE;
> - if (type == EGL_PBUFFER_BIT) {
> - dri2_surf->drawable = xcb_generate_id(dri2_dpy->conn);
> - s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn));
> - xcb_create_pixmap(dri2_dpy->conn,
> - _eglGetConfigKey(conf, EGL_BUFFER_SIZE),
> - dri2_surf->drawable, s.data->root,
> - dri2_surf->base.Width, dri2_surf->base.Height);
> - } else {
> - dri2_surf->drawable = window;
> - }
> -
> - dri2_surf->dri_drawable =
> - (*dri2_dpy->dri2->createNewDrawable) (dri2_dpy->dri_screen,
> - dri2_conf->dri_config, dri2_surf);
> - if (dri2_surf->dri_drawable == NULL) {
> - _eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable");
> - goto cleanup_pixmap;
> - }
> -
> - xcb_dri2_create_drawable (dri2_dpy->conn, dri2_surf->drawable);
> -
> - if (type != EGL_PBUFFER_BIT) {
> - cookie = xcb_get_geometry (dri2_dpy->conn, dri2_surf->drawable);
> - reply = xcb_get_geometry_reply (dri2_dpy->conn, cookie, &error);
> - if (reply == NULL || error != NULL) {
> - _eglError(EGL_BAD_ALLOC, "xcb_get_geometry");
> - free(error);
> - goto cleanup_dri_drawable;
> - }
> -
> - dri2_surf->base.Width = reply->width;
> - dri2_surf->base.Height = reply->height;
> - free(reply);
> - }
> -
> - return &dri2_surf->base;
> -
> - cleanup_dri_drawable:
> - dri2_dpy->core->destroyDrawable(dri2_surf->dri_drawable);
> - cleanup_pixmap:
> - if (type == EGL_PBUFFER_BIT)
> - xcb_free_pixmap(dri2_dpy->conn, dri2_surf->drawable);
> - cleanup_surf:
> - free(dri2_surf);
> -
> - return NULL;
> -}
> -
> -/**
> - * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
> - */
> -static _EGLSurface *
> -dri2_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp,
> - _EGLConfig *conf, EGLNativeWindowType window,
> - const EGLint *attrib_list)
> -{
> - return dri2_create_surface(drv, disp, EGL_WINDOW_BIT, conf,
> - window, attrib_list);
> -}
> -
> -static _EGLSurface *
> -dri2_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *disp,
> - _EGLConfig *conf, EGLNativePixmapType pixmap,
> - const EGLint *attrib_list)
> -{
> - return dri2_create_surface(drv, disp, EGL_PIXMAP_BIT, conf,
> - pixmap, attrib_list);
> -}
> -
> -static _EGLSurface *
> -dri2_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *disp,
> - _EGLConfig *conf, const EGLint *attrib_list)
> -{
> - return dri2_create_surface(drv, disp, EGL_PBUFFER_BIT, conf,
> - XCB_WINDOW_NONE, attrib_list);
> -}
> -
> -static EGLBoolean
> -dri2_copy_region(_EGLDriver *drv, _EGLDisplay *disp,
> - _EGLSurface *draw, xcb_xfixes_region_t region)
> -{
> - struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
> - struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
> - struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
> - _EGLContext *ctx;
> - xcb_dri2_copy_region_cookie_t cookie;
> -
> - if (dri2_drv->glFlush) {
> - ctx = _eglGetCurrentContext();
> - if (ctx && ctx->DrawSurface == &dri2_surf->base)
> - dri2_drv->glFlush();
> - }
> -
> - (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable);
> -
> -#if 0
> - /* FIXME: Add support for dri swapbuffers, that'll give us swap
> - * interval and page flipping (at least for fullscreen windows) as
> - * well as the page flip event. Unless surface->SwapBehavior is
> - * EGL_BUFFER_PRESERVED. */
> -#if __DRI2_FLUSH_VERSION >= 2
> - if (pdraw->psc->f)
> - (*pdraw->psc->f->flushInvalidate)(pdraw->driDrawable);
> -#endif
> -#endif
> -
> - if (!dri2_surf->have_fake_front)
> - return EGL_TRUE;
> -
> - cookie = xcb_dri2_copy_region_unchecked(dri2_dpy->conn,
> - dri2_surf->drawable,
> - region,
> - XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT,
> - XCB_DRI2_ATTACHMENT_BUFFER_FAKE_FRONT_LEFT);
> - free(xcb_dri2_copy_region_reply(dri2_dpy->conn, cookie, NULL));
> -
> - return EGL_TRUE;
> -}
> -
> -static EGLBoolean
> -dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
> -{
> - struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
> -
> - return dri2_copy_region(drv, disp, draw, dri2_surf->region);
> -}
> -
> -static EGLBoolean
> -dri2_swap_buffers_region(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw,
> - EGLint numRects, const EGLint *rects)
> -{
> - struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
> - struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
> - EGLBoolean ret;
> - xcb_xfixes_region_t region;
> - xcb_rectangle_t rectangles[16];
> - int i;
> -
> - if (numRects > ARRAY_SIZE(rectangles))
> - return dri2_copy_region(drv, disp, draw, dri2_surf->region);
> -
> - /* FIXME: Invert y here? */
> - for (i = 0; i < numRects; i++) {
> - rectangles[i].x = rects[i * 4];
> - rectangles[i].y = rects[i * 4 + 1];
> - rectangles[i].width = rects[i * 4 + 2];
> - rectangles[i].height = rects[i * 4 + 3];
> - }
> -
> - region = xcb_generate_id(dri2_dpy->conn);
> - xcb_xfixes_create_region(dri2_dpy->conn, region, numRects, rectangles);
> - ret = dri2_copy_region(drv, disp, draw, region);
> - xcb_xfixes_destroy_region(dri2_dpy->conn, region);
> -
> - return ret;
> -}
> -
> /*
> * Called from eglGetProcAddress() via drv->API.GetProcAddress().
> */
> @@ -1418,8 +510,9 @@ dri2_wait_client(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx)
>
> /* FIXME: If EGL allows frontbuffer rendering for window surfaces,
> * we need to copy fake to real here.*/
> -
> - (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable);
> + if (dri2_dpy->flush) {
> + (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable);
> + }
>
> return EGL_TRUE;
> }
> @@ -1427,48 +520,17 @@ dri2_wait_client(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx)
> static EGLBoolean
> dri2_wait_native(_EGLDriver *drv, _EGLDisplay *disp, EGLint engine)
> {
> - if (engine != EGL_CORE_NATIVE_ENGINE)
> + if (engine != EGL_CORE_NATIVE_ENGINE) {
> return _eglError(EGL_BAD_PARAMETER, "eglWaitNative");
> - /* glXWaitX(); */
> -
> - return EGL_TRUE;
> -}
> -
> -static void
> -dri2_unload(_EGLDriver *drv)
> -{
> - struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
> - free(dri2_drv);
> -}
> -
> -static EGLBoolean
> -dri2_copy_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
> - EGLNativePixmapType target)
> -{
> - struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
> - struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
> - xcb_gcontext_t gc;
> -
> - (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable);
> -
> - gc = xcb_generate_id(dri2_dpy->conn);
> - xcb_create_gc(dri2_dpy->conn, gc, target, 0, NULL);
> - xcb_copy_area(dri2_dpy->conn,
> - dri2_surf->drawable,
> - target,
> - gc,
> - 0, 0,
> - 0, 0,
> - dri2_surf->base.Width,
> - dri2_surf->base.Height);
> - xcb_free_gc(dri2_dpy->conn, gc);
> + /* glXWaitX(); */
> + }
>
> return EGL_TRUE;
> }
>
> static EGLBoolean
> dri2_bind_tex_image(_EGLDriver *drv,
> - _EGLDisplay *disp, _EGLSurface *surf, EGLint buffer)
> + _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);
> @@ -1502,387 +564,34 @@ dri2_bind_tex_image(_EGLDriver *drv,
> }
>
> (*dri2_dpy->tex_buffer->setTexBuffer2)(dri2_ctx->dri_context,
> - target, format,
> - dri2_surf->dri_drawable);
> + target, format,
> + dri2_surf->dri_drawable);
>
> return EGL_TRUE;
> }
>
> static EGLBoolean
> dri2_release_tex_image(_EGLDriver *drv,
> - _EGLDisplay *disp, _EGLSurface *surf, EGLint buffer)
> -{
> - return EGL_TRUE;
> -}
> -
> -static _EGLImage *
> -dri2_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx,
> - EGLClientBuffer buffer, const EGLint *attr_list)
> -{
> - struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
> - struct dri2_egl_image *dri2_img;
> - unsigned int attachments[1];
> - xcb_drawable_t drawable;
> - xcb_dri2_get_buffers_cookie_t buffers_cookie;
> - xcb_dri2_get_buffers_reply_t *buffers_reply;
> - xcb_dri2_dri2_buffer_t *buffers;
> - xcb_get_geometry_cookie_t geometry_cookie;
> - xcb_get_geometry_reply_t *geometry_reply;
> - xcb_generic_error_t *error;
> - int stride, format;
> -
> - drawable = (xcb_drawable_t) buffer;
> - xcb_dri2_create_drawable (dri2_dpy->conn, drawable);
> - attachments[0] = XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT;
> - buffers_cookie =
> - xcb_dri2_get_buffers_unchecked (dri2_dpy->conn,
> - drawable, 1, 1, attachments);
> - geometry_cookie = xcb_get_geometry (dri2_dpy->conn, drawable);
> - buffers_reply = xcb_dri2_get_buffers_reply (dri2_dpy->conn,
> - buffers_cookie, NULL);
> - buffers = xcb_dri2_get_buffers_buffers (buffers_reply);
> - if (buffers == NULL) {
> - return NULL;
> - }
> -
> - geometry_reply = xcb_get_geometry_reply (dri2_dpy->conn,
> - geometry_cookie, &error);
> - if (geometry_reply == NULL || error != NULL) {
> - _eglError(EGL_BAD_ALLOC, "xcb_get_geometry");
> - free(error);
> - free(buffers_reply);
> - }
> -
> - switch (geometry_reply->depth) {
> - case 16:
> - format = __DRI_IMAGE_FORMAT_RGB565;
> - break;
> - case 24:
> - format = __DRI_IMAGE_FORMAT_XRGB8888;
> - break;
> - case 32:
> - format = __DRI_IMAGE_FORMAT_ARGB8888;
> - break;
> - default:
> - _eglError(EGL_BAD_PARAMETER,
> - "dri2_create_image_khr: unsupported pixmap depth");
> - free(buffers_reply);
> - free(geometry_reply);
> - return NULL;
> - }
> -
> - dri2_img = malloc(sizeof *dri2_img);
> - if (!dri2_img) {
> - free(buffers_reply);
> - free(geometry_reply);
> - _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
> - return EGL_NO_IMAGE_KHR;
> - }
> -
> - if (!_eglInitImage(&dri2_img->base, disp, attr_list)) {
> - free(buffers_reply);
> - free(geometry_reply);
> - return EGL_NO_IMAGE_KHR;
> - }
> -
> - stride = buffers[0].pitch / buffers[0].cpp;
> - dri2_img->dri_image =
> - dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen,
> - buffers_reply->width,
> - buffers_reply->height,
> - format,
> - buffers[0].name,
> - stride,
> - dri2_img);
> -
> - free(buffers_reply);
> - free(geometry_reply);
> -
> - return &dri2_img->base;
> -}
> -
> -static _EGLImage *
> -dri2_create_image_khr_renderbuffer(_EGLDisplay *disp, _EGLContext *ctx,
> - 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 renderbuffer = (GLuint) buffer;
> -
> - if (renderbuffer == 0) {
> - _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, attr_list))
> - return EGL_NO_IMAGE_KHR;
> -
> - dri2_img->dri_image =
> - dri2_dpy->image->createImageFromRenderbuffer(dri2_ctx->dri_context,
> - renderbuffer,
> - dri2_img);
> -
> - return &dri2_img->base;
> -}
> -
> -static _EGLImage *
> -dri2_create_image_mesa_drm_buffer(_EGLDisplay *disp, _EGLContext *ctx,
> - EGLClientBuffer buffer, const EGLint *attr_list)
> -{
> - struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
> - struct dri2_egl_image *dri2_img;
> - EGLint width, height, format, name, stride, pitch, i, err;
> -
> - name = (EGLint) buffer;
> -
> - err = EGL_SUCCESS;
> - width = 0;
> - height = 0;
> - format = 0;
> - stride = 0;
> -
> - for (i = 0; attr_list[i] != EGL_NONE; i++) {
> - EGLint attr = attr_list[i++];
> - EGLint val = attr_list[i];
> -
> - switch (attr) {
> - case EGL_WIDTH:
> - width = val;
> - break;
> - case EGL_HEIGHT:
> - height = val;
> - break;
> - case EGL_DRM_BUFFER_FORMAT_MESA:
> - format = val;
> - break;
> - case EGL_DRM_BUFFER_STRIDE_MESA:
> - stride = val;
> - break;
> - default:
> - err = EGL_BAD_ATTRIBUTE;
> - break;
> - }
> -
> - if (err != EGL_SUCCESS) {
> - _eglLog(_EGL_WARNING, "bad image attribute 0x%04x", attr);
> - return NULL;
> - }
> - }
> -
> - if (width <= 0 || height <= 0 || stride <= 0) {
> - _eglError(EGL_BAD_PARAMETER,
> - "bad width, height or stride");
> - return NULL;
> - }
> -
> - switch (format) {
> - case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA:
> - format = __DRI_IMAGE_FORMAT_ARGB8888;
> - pitch = stride;
> - break;
> - default:
> - _eglError(EGL_BAD_PARAMETER,
> - "dri2_create_image_khr: unsupported pixmap depth");
> - return NULL;
> - }
> -
> - dri2_img = malloc(sizeof *dri2_img);
> - if (!dri2_img) {
> - _eglError(EGL_BAD_ALLOC, "dri2_create_image_mesa_drm");
> - return NULL;
> - }
> -
> - if (!_eglInitImage(&dri2_img->base, disp, attr_list)) {
> - free(dri2_img);
> - return NULL;
> - }
> -
> - dri2_img->dri_image =
> - dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen,
> - width,
> - height,
> - format,
> - name,
> - pitch,
> - dri2_img);
> - if (dri2_img->dri_image == NULL) {
> - free(dri2_img);
> - _eglError(EGL_BAD_ALLOC, "dri2_create_image_mesa_drm");
> - return NULL;
> - }
> -
> - return &dri2_img->base;
> -}
> -
> -static _EGLImage *
> -dri2_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
> - _EGLContext *ctx, EGLenum target,
> - EGLClientBuffer buffer, const EGLint *attr_list)
> -{
> - switch (target) {
> - case EGL_NATIVE_PIXMAP_KHR:
> - return dri2_create_image_khr_pixmap(disp, ctx, buffer, attr_list);
> - case EGL_GL_RENDERBUFFER_KHR:
> - return dri2_create_image_khr_renderbuffer(disp, ctx, buffer, attr_list);
> - case EGL_DRM_BUFFER_MESA:
> - return dri2_create_image_mesa_drm_buffer(disp, ctx, buffer, attr_list);
> - default:
> - _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
> - return EGL_NO_IMAGE_KHR;
> - }
> -}
> -
> -static EGLBoolean
> -dri2_destroy_image_khr(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *image)
> + _EGLDisplay *disp, _EGLSurface *surf, EGLint buffer)
> {
> - struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
> - struct dri2_egl_image *dri2_img = dri2_egl_image(image);
> -
> - dri2_dpy->image->destroyImage(dri2_img->dri_image);
> - free(dri2_img);
> -
> return EGL_TRUE;
> }
>
> -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;
> - int width, height, format, i;
> - unsigned int use, dri_use, valid_mask;
> - EGLint err = EGL_SUCCESS;
> -
> - 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;
> - }
> -
> - if (!_eglInitImage(&dri2_img->base, disp, attr_list)) {
> - err = EGL_BAD_PARAMETER;
> - goto cleanup_img;
> - }
> -
> - width = 0;
> - height = 0;
> - format = 0;
> - use = 0;
> - for (i = 0; attr_list[i] != EGL_NONE; i++) {
> - EGLint attr = attr_list[i++];
> - EGLint val = attr_list[i];
> -
> - switch (attr) {
> - case EGL_WIDTH:
> - width = val;
> - break;
> - case EGL_HEIGHT:
> - height = val;
> - break;
> - case EGL_DRM_BUFFER_FORMAT_MESA:
> - format = val;
> - break;
> - case EGL_DRM_BUFFER_USE_MESA:
> - use = val;
> - break;
> - default:
> - err = EGL_BAD_ATTRIBUTE;
> - break;
> - }
> -
> - if (err != EGL_SUCCESS) {
> - _eglLog(_EGL_WARNING, "bad image attribute 0x%04x", attr);
> - goto cleanup_img;
> - }
> - }
> -
> - if (width <= 0 || height <= 0) {
> - _eglLog(_EGL_WARNING, "bad width or height (%dx%d)", width, height);
> - goto cleanup_img;
> - }
> -
> - switch (format) {
> - case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA:
> - format = __DRI_IMAGE_FORMAT_ARGB8888;
> - break;
> - default:
> - _eglLog(_EGL_WARNING, "bad image format value 0x%04x", format);
> - goto cleanup_img;
> - }
> -
> - valid_mask =
> - EGL_DRM_BUFFER_USE_SCANOUT_MESA |
> - EGL_DRM_BUFFER_USE_SHARE_MESA;
> - if (use & ~valid_mask) {
> - _eglLog(_EGL_WARNING, "bad image use bit 0x%04x", use & ~valid_mask);
> - goto cleanup_img;
> - }
> -
> - dri_use = 0;
> - if (use & EGL_DRM_BUFFER_USE_SHARE_MESA)
> - dri_use |= __DRI_IMAGE_USE_SHARE;
> - if (use & EGL_DRM_BUFFER_USE_SCANOUT_MESA)
> - dri_use |= __DRI_IMAGE_USE_SCANOUT;
> -
> - dri2_img->dri_image =
> - dri2_dpy->image->createImage(dri2_dpy->dri_screen,
> - width, height, format, dri_use, dri2_img);
> - 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)
> +static void
> +dri2_unload(_EGLDriver *drv)
> {
> - struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
> - struct dri2_egl_image *dri2_img = dri2_egl_image(img);
> -
> - 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;
> + struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
> + free(dri2_drv);
> }
>
> /**
> * This is the main entrypoint into the driver, called by libEGL.
> - * Create a new _EGLDriver object and init its dispatch table.
> + * Create a new _EGLDriver object and init the common part of its
> + * dispatch table. The other parts of dispatch table initialization
> + * is deferred to dri2_initialize as drm, x11_dri2 and x11_swrast
> + * have different dispatch table assignment.
> */
> +
> _EGLDriver *
> _eglMain(const char *args)
> {
> @@ -1894,32 +603,23 @@ _eglMain(const char *args)
>
> memset(dri2_drv, 0, sizeof *dri2_drv);
> _eglInitDriverFallbacks(&dri2_drv->base);
> +
> + // common initialization between drm, x11_dri2 and x11_swrast
> dri2_drv->base.API.Initialize = dri2_initialize;
> - dri2_drv->base.API.Terminate = dri2_terminate;
> dri2_drv->base.API.CreateContext = dri2_create_context;
> dri2_drv->base.API.MakeCurrent = dri2_make_current;
> - dri2_drv->base.API.CreateWindowSurface = dri2_create_window_surface;
> - dri2_drv->base.API.CreatePixmapSurface = dri2_create_pixmap_surface;
> - dri2_drv->base.API.CreatePbufferSurface = dri2_create_pbuffer_surface;
> - dri2_drv->base.API.DestroySurface = dri2_destroy_surface;
> - dri2_drv->base.API.SwapBuffers = dri2_swap_buffers;
> 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;
> - dri2_drv->base.API.CopyBuffers = dri2_copy_buffers;
> dri2_drv->base.API.BindTexImage = dri2_bind_tex_image;
> dri2_drv->base.API.ReleaseTexImage = dri2_release_tex_image;
> - dri2_drv->base.API.CreateImageKHR = dri2_create_image_khr;
> - dri2_drv->base.API.DestroyImageKHR = dri2_destroy_image_khr;
> - dri2_drv->base.API.SwapBuffersRegionNOK = dri2_swap_buffers_region;
> - dri2_drv->base.API.CreateDRMImageMESA = dri2_create_drm_image_mesa;
> - dri2_drv->base.API.ExportDRMImageMESA = dri2_export_drm_image_mesa;
> + dri2_drv->base.Unload = dri2_unload;
>
> dri2_drv->base.Name = "DRI2";
> - dri2_drv->base.Unload = dri2_unload;
>
> dri2_drv->glFlush =
> (void (*)(void)) dri2_get_proc_address(&dri2_drv->base, "glFlush");
>
> return &dri2_drv->base;
> }
> +
> diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h
> new file mode 100644
> index 0000000..206aafc
> --- /dev/null
> +++ b/src/egl/drivers/dri2/egl_dri2.h
> @@ -0,0 +1,148 @@
> +/*
> + * 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 at bitplanet.net>
> + */
> +
> +#ifndef EGL_DRI2_INCLUDED
> +#define EGL_DRI2_INCLUDED
> +
> +#include <stdlib.h>
> +#include <string.h>
> +#include <stdio.h>
> +#include <limits.h>
> +#include <dlfcn.h>
> +#include <fcntl.h>
> +#include <errno.h>
> +#include <unistd.h>
> +#include <GL/gl.h>
> +#include <GL/internal/dri_interface.h>
> +#include <sys/types.h>
> +#include <sys/stat.h>
> +
> +#include <glapi/glapi.h>
> +#include "eglconfig.h"
> +#include "eglcontext.h"
> +#include "egldisplay.h"
> +#include "egldriver.h"
> +#include "eglcurrent.h"
> +#include "egllog.h"
> +#include "eglsurface.h"
> +#include "eglimage.h"
> +
> +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
> +
> +struct dri2_egl_driver
> +{
> + _EGLDriver base;
> +
> + void (*glFlush)(void);
> +};
> +
> +struct dri2_egl_display
> +{
> + __DRIscreen *dri_screen;
> + const __DRIconfig **driver_configs;
> + void *driver;
> + __DRIcoreExtension *core;
> + __DRIdri2Extension *dri2;
> + __DRIswrastExtension *swrast;
> + __DRI2flushExtension *flush;
> + __DRItexBufferExtension *tex_buffer;
> + __DRIimageExtension *image;
> +
> + char *driver_name;
> + int fd;
> +
> + __DRIdri2LoaderExtension dri2_loader_extension;
> + __DRIswrastLoaderExtension swrast_loader_extension;
> + const __DRIextension *extensions[3];
> +};
> +
> +struct dri2_egl_context
> +{
> + _EGLContext base;
> + __DRIcontext *dri_context;
> +};
> +
> +struct dri2_egl_surface
> +{
> + _EGLSurface base;
> + __DRIdrawable *dri_drawable;
> +};
> +
> +struct dri2_egl_config
> +{
> + _EGLConfig base;
> + const __DRIconfig *dri_config;
> +};
> +
> +struct dri2_egl_image
> +{
> + _EGLImage base;
> + __DRIimage *dri_image;
> +};
> +
> +struct dri2_extension_match {
> + const char *name;
> + int version;
> + int offset;
> +};
> +
> +/* standard typecasts */
> +_EGL_DRIVER_STANDARD_TYPECASTS(dri2_egl)
> +_EGL_DRIVER_TYPECAST(dri2_egl_image, _EGLImage, obj)
> +
> +char *
> +dri2_strndup(const char *s, int length);
> +
> +const __DRIextension **
> +dri2_load_driver(_EGLDisplay *disp);
> +
> +EGLBoolean
> +dri2_bind_extensions(struct dri2_egl_display *dri2_dpy,
> + struct dri2_extension_match *matches,
> + const __DRIextension **extensions);
> +
> +struct dri2_egl_config *
> +dri2_add_config(_EGLDisplay *disp,
> + const __DRIconfig *dri_config, int id,
> + int depth, EGLint surface_type, int accel);
> +
> +EGLBoolean
> +dri2_initialize_x11(_EGLDriver *drv,
> + _EGLDisplay *disp,
> + EGLint *major,
> + EGLint *minor);
> +
> +#ifdef HAVE_LIBUDEV
> +EGLBoolean
> +dri2_initialize_drm(_EGLDriver *drv,
> + _EGLDisplay *disp,
> + EGLint *major,
> + EGLint *minor);
> +#endif
> +
> +#endif
> +
> diff --git a/src/egl/drivers/dri2/x11_dri2.c b/src/egl/drivers/dri2/x11_dri2.c
> new file mode 100644
> index 0000000..fba457c
> --- /dev/null
> +++ b/src/egl/drivers/dri2/x11_dri2.c
> @@ -0,0 +1,745 @@
> +/*
> + * 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 at bitplanet.net>
> + */
> +
> +#include "x11_shared.h"
> +#include "dri2_shared.h"
> +#include <xf86drm.h>
> +#include <xcb/dri2.h>
> +
> +struct dri2_egl_x11_dri2_display
> +{
> + struct dri2_egl_x11_display base;
> + int dri2_major;
> + int dri2_minor;
> + char *device_name;
> +};
> +
> +struct dri2_egl_x11_dri2_surface
> +{
> + struct dri2_egl_x11_surface base;
> + __DRIbuffer buffers[5];
> + int buffer_count;
> + xcb_xfixes_region_t region;
> + int have_fake_front;
> + int swap_interval;
> +};
> +
> +extern const __DRIimageLookupExtension image_lookup_extension;
> +extern struct dri2_extension_match dri2_driver_extensions[];
> +extern struct dri2_extension_match dri2_core_extensions[];
> +
> +/* typecasts */
> +_EGL_DRIVER_TYPECAST(dri2_egl_x11_dri2_display, _EGLDisplay, obj->DriverData)
> +_EGL_DRIVER_TYPECAST(dri2_egl_x11_dri2_surface, _EGLSurface, obj)
> +
> +/**
> + * Process list of buffer received from the server
> + *
> + * Processes the list of buffers received in a reply from the server to either
> + * \c DRI2GetBuffers or \c DRI2GetBuffersWithFormat.
> + */
> +static void
> +dri2_process_buffers(struct dri2_egl_x11_dri2_surface *dri2_surf,
> + xcb_dri2_dri2_buffer_t *buffers, unsigned count)
> +{
> + struct dri2_egl_x11_dri2_display *dri2_dpy =
> + dri2_egl_x11_dri2_display(dri2_surf->base.base.base.Resource.Display);
> + xcb_rectangle_t rectangle;
> + int i;
> +
> + dri2_surf->buffer_count = count;
> + dri2_surf->have_fake_front = 0;
> +
> + /* This assumes the DRI2 buffer attachment tokens matches the
> + * __DRIbuffer tokens. */
> + for (i = 0; i < count; i++) {
> + dri2_surf->buffers[i].attachment = buffers[i].attachment;
> + dri2_surf->buffers[i].name = buffers[i].name;
> + dri2_surf->buffers[i].pitch = buffers[i].pitch;
> + dri2_surf->buffers[i].cpp = buffers[i].cpp;
> + dri2_surf->buffers[i].flags = buffers[i].flags;
> +
> + /* We only use the DRI drivers single buffer configs. This
> + * means that if we try to render to a window, DRI2 will give us
> + * the fake front buffer, which we'll use as a back buffer.
> + * Note that EGL doesn't require that several clients rendering
> + * to the same window must see the same aux buffers. */
> + if (dri2_surf->buffers[i].attachment == __DRI_BUFFER_FAKE_FRONT_LEFT)
> + dri2_surf->have_fake_front = 1;
> + }
> +
> + if (dri2_surf->region != XCB_NONE)
> + xcb_xfixes_destroy_region(dri2_dpy->base.conn, dri2_surf->region);
> +
> + rectangle.x = 0;
> + rectangle.y = 0;
> + rectangle.width = dri2_surf->base.base.base.Width;
> + rectangle.height = dri2_surf->base.base.base.Height;
> + dri2_surf->region = xcb_generate_id(dri2_dpy->base.conn);
> + xcb_xfixes_create_region(dri2_dpy->base.conn, dri2_surf->region, 1, &rectangle);
> +}
> +
> +static __DRIbuffer *
> +dri2_get_buffers(__DRIdrawable * driDrawable,
> + int *width, int *height,
> + unsigned int *attachments, int count,
> + int *out_count, void *loaderPrivate)
> +{
> + struct dri2_egl_x11_dri2_surface *dri2_surf = loaderPrivate;
> + struct dri2_egl_x11_dri2_display *dri2_dpy =
> + dri2_egl_x11_dri2_display(dri2_surf->base.base.base.Resource.Display);
> + xcb_dri2_dri2_buffer_t *buffers;
> + xcb_dri2_get_buffers_reply_t *reply;
> + xcb_dri2_get_buffers_cookie_t cookie;
> +
> + cookie = xcb_dri2_get_buffers_unchecked (dri2_dpy->base.conn,
> + dri2_surf->base.drawable,
> + count, count, attachments);
> + reply = xcb_dri2_get_buffers_reply (dri2_dpy->base.conn, cookie, NULL);
> + buffers = xcb_dri2_get_buffers_buffers (reply);
> + if (buffers == NULL)
> + return NULL;
> +
> + *out_count = reply->count;
> + dri2_surf->base.base.base.Width = *width = reply->width;
> + dri2_surf->base.base.base.Height = *height = reply->height;
> + dri2_process_buffers(dri2_surf, buffers, *out_count);
> +
> + free(reply);
> +
> + return dri2_surf->buffers;
> +}
> +
> +static void
> +dri2_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate)
> +{
> + /* FIXME: Does EGL support front buffer rendering at all? */
> +
> +#if 0
> + struct dri2_egl_surface *dri2_surf = loaderPrivate;
> +
> + dri2WaitGL(dri2_surf);
> +#endif
> +}
> +
> +
> +static __DRIbuffer *
> +dri2_get_buffers_with_format(__DRIdrawable * driDrawable,
> + int *width, int *height,
> + unsigned int *attachments, int count,
> + int *out_count, void *loaderPrivate)
> +{
> + struct dri2_egl_x11_dri2_surface *dri2_surf = loaderPrivate;
> + struct dri2_egl_x11_dri2_display *dri2_dpy =
> + dri2_egl_x11_dri2_display(dri2_surf->base.base.base.Resource.Display);
> + xcb_dri2_dri2_buffer_t *buffers;
> + xcb_dri2_get_buffers_with_format_reply_t *reply;
> + xcb_dri2_get_buffers_with_format_cookie_t cookie;
> + xcb_dri2_attach_format_t *format_attachments;
> +
> + format_attachments = (xcb_dri2_attach_format_t *) attachments;
> + cookie = xcb_dri2_get_buffers_with_format_unchecked (dri2_dpy->base.conn,
> + dri2_surf->base.drawable,
> + count, count,
> + format_attachments);
> +
> + reply = xcb_dri2_get_buffers_with_format_reply (dri2_dpy->base.conn,
> + cookie, NULL);
> + if (reply == NULL)
> + return NULL;
> +
> + buffers = xcb_dri2_get_buffers_with_format_buffers (reply);
> + dri2_surf->base.base.base.Width = *width = reply->width;
> + dri2_surf->base.base.base.Height = *height = reply->height;
> + *out_count = reply->count;
> + dri2_process_buffers(dri2_surf, buffers, *out_count);
> +
> + free(reply);
> +
> + return dri2_surf->buffers;
> +}
> +
> +static EGLBoolean
> +dri2_connect(struct dri2_egl_x11_dri2_display *dri2_dpy)
> +{
> + xcb_xfixes_query_version_reply_t *xfixes_query;
> + xcb_xfixes_query_version_cookie_t xfixes_query_cookie;
> + xcb_dri2_query_version_reply_t *dri2_query;
> + xcb_dri2_query_version_cookie_t dri2_query_cookie;
> + xcb_dri2_connect_reply_t *connect;
> + xcb_dri2_connect_cookie_t connect_cookie;
> + xcb_generic_error_t *error;
> + xcb_screen_iterator_t s;
> +
> + xcb_prefetch_extension_data (dri2_dpy->base.conn, &xcb_xfixes_id);
> + xcb_prefetch_extension_data (dri2_dpy->base.conn, &xcb_dri2_id);
> +
> + xfixes_query_cookie = xcb_xfixes_query_version(dri2_dpy->base.conn,
> + XCB_XFIXES_MAJOR_VERSION,
> + XCB_XFIXES_MINOR_VERSION);
> +
> + dri2_query_cookie = xcb_dri2_query_version (dri2_dpy->base.conn,
> + XCB_DRI2_MAJOR_VERSION,
> + XCB_DRI2_MINOR_VERSION);
> +
> + s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->base.conn));
> + connect_cookie = xcb_dri2_connect_unchecked (dri2_dpy->base.conn,
> + s.data->root,
> + XCB_DRI2_DRIVER_TYPE_DRI);
> +
> + xfixes_query =
> + xcb_xfixes_query_version_reply (dri2_dpy->base.conn,
> + xfixes_query_cookie, &error);
> + if (xfixes_query == NULL ||
> + error != NULL || xfixes_query->major_version < 2) {
> + _eglLog(_EGL_FATAL, "DRI2: failed to query xfixes version");
> + free(error);
> + return EGL_FALSE;
> + }
> + free(xfixes_query);
> +
> + dri2_query =
> + xcb_dri2_query_version_reply (dri2_dpy->base.conn, dri2_query_cookie, &error);
> + if (dri2_query == NULL || error != NULL) {
> + _eglLog(_EGL_FATAL, "DRI2: failed to query version");
> + free(error);
> + return EGL_FALSE;
> + }
> + dri2_dpy->dri2_major = dri2_query->major_version;
> + dri2_dpy->dri2_minor = dri2_query->minor_version;
> + free(dri2_query);
> +
> + connect = xcb_dri2_connect_reply (dri2_dpy->base.conn, connect_cookie, NULL);
> + if (connect == NULL ||
> + connect->driver_name_length + connect->device_name_length == 0) {
> + _eglLog(_EGL_FATAL, "DRI2: failed to authenticate");
> + return EGL_FALSE;
> + }
> +
> + dri2_dpy->device_name =
> + dri2_strndup(xcb_dri2_connect_device_name (connect),
> + xcb_dri2_connect_device_name_length (connect));
> +
> + dri2_dpy->base.base.driver_name =
> + dri2_strndup(xcb_dri2_connect_driver_name (connect),
> + xcb_dri2_connect_driver_name_length (connect));
> +
> + if (dri2_dpy->device_name == NULL || dri2_dpy->base.base.driver_name == NULL) {
> + free(dri2_dpy->device_name);
> + free(dri2_dpy->base.base.driver_name);
> + free(connect);
> + return EGL_FALSE;
> + }
> + free(connect);
> +
> + return EGL_TRUE;
> +}
> +
> +static EGLBoolean
> +dri2_authenticate(struct dri2_egl_x11_dri2_display *dri2_dpy)
> +{
> + xcb_dri2_authenticate_reply_t *authenticate;
> + xcb_dri2_authenticate_cookie_t authenticate_cookie;
> + xcb_screen_iterator_t s;
> + drm_magic_t magic;
> +
> + if (drmGetMagic(dri2_dpy->base.base.fd, &magic)) {
> + _eglLog(_EGL_FATAL, "DRI2: failed to get drm magic");
> + return EGL_FALSE;
> + }
> +
> + s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->base.conn));
> + authenticate_cookie =
> + xcb_dri2_authenticate_unchecked(dri2_dpy->base.conn, s.data->root, magic);
> + authenticate =
> + xcb_dri2_authenticate_reply(dri2_dpy->base.conn, authenticate_cookie, NULL);
> + if (authenticate == NULL || !authenticate->authenticated) {
> + _eglLog(_EGL_FATAL, "DRI2: failed to authenticate");
> + free(authenticate);
> + return EGL_FALSE;
> + }
> +
> + free(authenticate);
> +
> + return EGL_TRUE;
> +}
> +
> +static EGLBoolean
> +dri2_copy_region(_EGLDriver *drv, _EGLDisplay *disp,
> + _EGLSurface *draw, xcb_xfixes_region_t region)
> +{
> + struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
> + struct dri2_egl_x11_dri2_display *dri2_dpy = dri2_egl_x11_dri2_display(disp);
> + struct dri2_egl_x11_dri2_surface *dri2_surf = dri2_egl_x11_dri2_surface(draw);
> + _EGLContext *ctx;
> + xcb_dri2_copy_region_cookie_t cookie;
> +
> + if (dri2_drv->glFlush) {
> + ctx = _eglGetCurrentContext();
> + if (ctx && ctx->DrawSurface == &dri2_surf->base.base.base)
> + dri2_drv->glFlush();
> + }
> +
> + (*dri2_dpy->base.base.flush->flush)(dri2_surf->base.base.dri_drawable);
> +
> +#if 0
> + /* FIXME: Add support for dri swapbuffers, that'll give us swap
> + * interval and page flipping (at least for fullscreen windows) as
> + * well as the page flip event. Unless surface->SwapBehavior is
> + * EGL_BUFFER_PRESERVED. */
> +#if __DRI2_FLUSH_VERSION >= 2
> + if (pdraw->psc->f)
> + (*pdraw->psc->f->flushInvalidate)(pdraw->driDrawable);
> +#endif
> +#endif
> +
> + if (!dri2_surf->have_fake_front)
> + return EGL_TRUE;
> +
> + cookie = xcb_dri2_copy_region_unchecked(dri2_dpy->base.conn,
> + dri2_surf->base.drawable,
> + region,
> + XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT,
> + XCB_DRI2_ATTACHMENT_BUFFER_FAKE_FRONT_LEFT);
> + free(xcb_dri2_copy_region_reply(dri2_dpy->base.conn, cookie, NULL));
> +
> + return EGL_TRUE;
> +}
> +
> +static EGLBoolean
> +dri2_swap_buffers_region(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw,
> + EGLint numRects, const EGLint *rects)
> +{
> + struct dri2_egl_x11_dri2_display *dri2_dpy = dri2_egl_x11_dri2_display(disp);
> + struct dri2_egl_x11_dri2_surface *dri2_surf = dri2_egl_x11_dri2_surface(draw);
> + EGLBoolean ret;
> + xcb_xfixes_region_t region;
> + xcb_rectangle_t rectangles[16];
> + int i;
> +
> + if (numRects > ARRAY_SIZE(rectangles))
> + return dri2_copy_region(drv, disp, draw, dri2_surf->region);
> +
> + /* FIXME: Invert y here? */
> + for (i = 0; i < numRects; i++) {
> + rectangles[i].x = rects[i * 4];
> + rectangles[i].y = rects[i * 4 + 1];
> + rectangles[i].width = rects[i * 4 + 2];
> + rectangles[i].height = rects[i * 4 + 3];
> + }
> +
> + region = xcb_generate_id(dri2_dpy->base.conn);
> + xcb_xfixes_create_region(dri2_dpy->base.conn, region, numRects, rectangles);
> + ret = dri2_copy_region(drv, disp, draw, region);
> + xcb_xfixes_destroy_region(dri2_dpy->base.conn, region);
> +
> + return ret;
> +}
> +
> +static EGLBoolean
> +dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
> +{
> + struct dri2_egl_x11_dri2_surface *dri2_surf = dri2_egl_x11_dri2_surface(draw);
> +
> + return dri2_copy_region(drv, disp, draw, dri2_surf->region);
> +}
> +
> +static _EGLImage *
> +dri2_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx,
> + EGLClientBuffer buffer, const EGLint *attr_list)
> +{
> + struct dri2_egl_x11_dri2_display *dri2_dpy = dri2_egl_x11_dri2_display(disp);
> + struct dri2_egl_image *dri2_img;
> + unsigned int attachments[1];
> + xcb_drawable_t drawable;
> + xcb_dri2_get_buffers_cookie_t buffers_cookie;
> + xcb_dri2_get_buffers_reply_t *buffers_reply;
> + xcb_dri2_dri2_buffer_t *buffers;
> + xcb_get_geometry_cookie_t geometry_cookie;
> + xcb_get_geometry_reply_t *geometry_reply;
> + xcb_generic_error_t *error;
> + int stride, format;
> +
> + drawable = (xcb_drawable_t) buffer;
> + xcb_dri2_create_drawable (dri2_dpy->base.conn, drawable);
> + attachments[0] = XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT;
> + buffers_cookie =
> + xcb_dri2_get_buffers_unchecked (dri2_dpy->base.conn,
> + drawable, 1, 1, attachments);
> + geometry_cookie = xcb_get_geometry (dri2_dpy->base.conn, drawable);
> + buffers_reply = xcb_dri2_get_buffers_reply (dri2_dpy->base.conn,
> + buffers_cookie, NULL);
> + buffers = xcb_dri2_get_buffers_buffers (buffers_reply);
> + if (buffers == NULL) {
> + return NULL;
> + }
> +
> + geometry_reply = xcb_get_geometry_reply (dri2_dpy->base.conn,
> + geometry_cookie, &error);
> + if (geometry_reply == NULL || error != NULL) {
> + _eglError(EGL_BAD_ALLOC, "xcb_get_geometry");
> + free(error);
> + free(buffers_reply);
> + }
> +
> + switch (geometry_reply->depth) {
> + case 16:
> + format = __DRI_IMAGE_FORMAT_RGB565;
> + break;
> + case 24:
> + format = __DRI_IMAGE_FORMAT_XRGB8888;
> + break;
> + case 32:
> + format = __DRI_IMAGE_FORMAT_ARGB8888;
> + break;
> + default:
> + _eglError(EGL_BAD_PARAMETER,
> + "dri2_create_image_khr: unsupported pixmap depth");
> + free(buffers_reply);
> + free(geometry_reply);
> + return NULL;
> + }
> +
> + dri2_img = malloc(sizeof *dri2_img);
> + if (!dri2_img) {
> + free(buffers_reply);
> + free(geometry_reply);
> + _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr");
> + return EGL_NO_IMAGE_KHR;
> + }
> +
> + if (!_eglInitImage(&dri2_img->base, disp, attr_list)) {
> + free(buffers_reply);
> + free(geometry_reply);
> + return EGL_NO_IMAGE_KHR;
> + }
> +
> + stride = buffers[0].pitch / buffers[0].cpp;
> + dri2_img->dri_image =
> + dri2_dpy->base.base.image->createImageFromName(dri2_dpy->base.base.dri_screen,
> + buffers_reply->width,
> + buffers_reply->height,
> + format,
> + buffers[0].name,
> + stride,
> + dri2_img);
> +
> + free(buffers_reply);
> + free(geometry_reply);
> +
> + return &dri2_img->base;
> +}
> +
> +/**
> + * Called via eglTerminate(), drv->API.Terminate().
> + */
> +static EGLBoolean
> +dri2_x11_dri2_terminate(_EGLDriver *drv, _EGLDisplay *disp)
> +{
> + struct dri2_egl_x11_dri2_display *dri2_dpy = dri2_egl_x11_dri2_display(disp);
> +
> + _eglReleaseDisplayResources(drv, disp);
> + _eglCleanupDisplay(disp);
> +
> + dri2_dpy->base.base.core->destroyScreen(dri2_dpy->base.base.dri_screen);
> + close(dri2_dpy->base.base.fd);
> + dlclose(dri2_dpy->base.base.driver);
> + if (disp->PlatformDisplay == NULL)
> + xcb_disconnect(dri2_dpy->base.conn);
> + free(dri2_dpy);
> + disp->DriverData = NULL;
> +
> + return EGL_TRUE;
> +}
> +
> +static _EGLSurface *
> +dri2_x11_dri2_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
> + _EGLConfig *conf, EGLNativeWindowType window,
> + const EGLint *attrib_list)
> +{
> + struct dri2_egl_x11_display *dri2_dpy = dri2_egl_x11_display(disp);
> + struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
> + struct dri2_egl_x11_dri2_surface *dri2_surf;
> + xcb_get_geometry_cookie_t cookie;
> + xcb_get_geometry_reply_t *reply;
> + xcb_screen_iterator_t s;
> + xcb_generic_error_t *error;
> +
> + dri2_surf = malloc(sizeof *dri2_surf);
> + if (!dri2_surf) {
> + _eglError(EGL_BAD_ALLOC, "dri2_create_surface");
> + return NULL;
> + }
> +
> + if (!_eglInitSurface(&dri2_surf->base.base.base, disp, type, conf, attrib_list))
> + goto cleanup_surf;
> +
> + dri2_surf->region = XCB_NONE;
> + if (type == EGL_PBUFFER_BIT) {
> + dri2_surf->base.drawable = xcb_generate_id(dri2_dpy->conn);
> + s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn));
> + xcb_create_pixmap(dri2_dpy->conn,
> + _eglGetConfigKey(conf, EGL_BUFFER_SIZE),
> + dri2_surf->base.drawable, s.data->root,
> + dri2_surf->base.base.base.Width, dri2_surf->base.base.base.Height);
> + } else {
> + dri2_surf->base.drawable = window;
> + }
> +
> + dri2_surf->base.base.dri_drawable =
> + (*dri2_dpy->base.dri2->createNewDrawable) (dri2_dpy->base.dri_screen,
> + dri2_conf->dri_config, dri2_surf);
> +
> + if (dri2_surf->base.base.dri_drawable == NULL) {
> + _eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable");
> + goto cleanup_pixmap;
> + }
> +
> + xcb_dri2_create_drawable (dri2_dpy->conn, dri2_surf->base.drawable);
> +
> + if (type != EGL_PBUFFER_BIT) {
> + cookie = xcb_get_geometry (dri2_dpy->conn, dri2_surf->base.drawable);
> + reply = xcb_get_geometry_reply (dri2_dpy->conn, cookie, &error);
> + if (reply == NULL || error != NULL) {
> + _eglError(EGL_BAD_ALLOC, "xcb_get_geometry");
> + free(error);
> + goto cleanup_dri_drawable;
> + }
> +
> + dri2_surf->base.base.base.Width = reply->width;
> + dri2_surf->base.base.base.Height = reply->height;
> + free(reply);
> + }
> +
> + return &dri2_surf->base.base.base;
> +
> + cleanup_dri_drawable:
> + dri2_dpy->base.core->destroyDrawable(dri2_surf->base.base.dri_drawable);
> + cleanup_pixmap:
> + if (type == EGL_PBUFFER_BIT)
> + xcb_free_pixmap(dri2_dpy->conn, dri2_surf->base.drawable);
> + cleanup_surf:
> + free(dri2_surf);
> +
> + return NULL;
> +}
> +
> +/**
> + * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
> + */
> +static _EGLSurface *
> +dri2_x11_dri2_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp,
> + _EGLConfig *conf, EGLNativeWindowType window,
> + const EGLint *attrib_list)
> +{
> + return dri2_x11_dri2_create_surface(drv, disp, EGL_WINDOW_BIT, conf,
> + window, attrib_list);
> +}
> +
> +static _EGLSurface *
> +dri2_x11_dri2_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *disp,
> + _EGLConfig *conf, EGLNativePixmapType pixmap,
> + const EGLint *attrib_list)
> +{
> + return dri2_x11_dri2_create_surface(drv, disp, EGL_PIXMAP_BIT, conf,
> + pixmap, attrib_list);
> +}
> +
> +static _EGLSurface *
> +dri2_x11_dri2_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *disp,
> + _EGLConfig *conf, const EGLint *attrib_list)
> +{
> + return dri2_x11_dri2_create_surface(drv, disp, EGL_PBUFFER_BIT, conf,
> + XCB_WINDOW_NONE, attrib_list);
> +}
> +
> +static EGLBoolean
> +dri2_x11_dri2_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
> +{
> + struct dri2_egl_x11_display *dri2_dpy = dri2_egl_x11_display(disp);
> + struct dri2_egl_x11_dri2_surface *dri2_surf = dri2_egl_x11_dri2_surface(surf);
> +
> + if (_eglIsSurfaceBound(surf))
> + return EGL_TRUE;
> +
> + (*dri2_dpy->base.core->destroyDrawable)(dri2_surf->base.base.dri_drawable);
> +
> + xcb_dri2_destroy_drawable (dri2_dpy->conn, dri2_surf->base.drawable);
> +
> + if (surf->Type == EGL_PBUFFER_BIT)
> + xcb_free_pixmap (dri2_dpy->conn, dri2_surf->base.drawable);
> +
> + free(surf);
> +
> + return EGL_TRUE;
> +}
> +
> +static _EGLImage *
> +dri2_x11_dri2_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
> + _EGLContext *ctx, EGLenum target,
> + EGLClientBuffer buffer, const EGLint *attr_list)
> +{
> + if (target == EGL_NATIVE_PIXMAP_KHR) {
> + return dri2_create_image_khr_pixmap(disp, ctx, buffer, attr_list);
> + } else {
> + return dri2_create_image_khr(drv, disp, ctx, target, buffer, attr_list);
> + }
> +}
> +
> +static void
> +dri2_x11_dri2_initialize_driver(_EGLDriver *drv)
> +{
> + struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
> +
> + dri2_drv->base.API.Terminate = dri2_x11_dri2_terminate;
> + dri2_drv->base.API.CreateWindowSurface = dri2_x11_dri2_create_window_surface;
> + dri2_drv->base.API.CreatePixmapSurface = dri2_x11_dri2_create_pixmap_surface;
> + dri2_drv->base.API.CreatePbufferSurface = dri2_x11_dri2_create_pbuffer_surface;
> + dri2_drv->base.API.DestroySurface = dri2_x11_dri2_destroy_surface;
> + dri2_drv->base.API.SwapBuffers = dri2_swap_buffers;
> + dri2_drv->base.API.CopyBuffers = dri2_copy_buffers;
> + dri2_drv->base.API.CreateImageKHR = dri2_x11_dri2_create_image_khr;
> + dri2_drv->base.API.DestroyImageKHR = dri2_destroy_image_khr;
> + dri2_drv->base.API.SwapBuffersRegionNOK = dri2_swap_buffers_region;
> + dri2_drv->base.API.CreateDRMImageMESA = dri2_create_drm_image_mesa;
> + dri2_drv->base.API.ExportDRMImageMESA = dri2_export_drm_image_mesa;
> +
> + dri2_drv->base.Name = "DRI2_X11_DRI2";
> +}
> +
> +EGLBoolean
> +dri2_initialize_x11_dri2(_EGLDriver *drv, _EGLDisplay *disp,
> + EGLint *major, EGLint *minor)
> +{
> + struct dri2_egl_x11_dri2_display *dri2_dpy;
> + const __DRIextension **extensions;
> +
> + dri2_dpy = malloc(sizeof *dri2_dpy);
> + if (!dri2_dpy)
> + return _eglError(EGL_BAD_ALLOC, "eglInitialize");
> +
> + memset(dri2_dpy, 0, sizeof *dri2_dpy);
> +
> + disp->DriverData = (void *) dri2_dpy;
> + if (disp->PlatformDisplay == NULL) {
> + dri2_dpy->base.conn = xcb_connect(0, 0);
> + } else {
> + dri2_dpy->base.conn = XGetXCBConnection((Display *) disp->PlatformDisplay);
> + }
> +
> + if (xcb_connection_has_error(dri2_dpy->base.conn)) {
> + _eglLog(_EGL_WARNING, "DRI2: xcb_connect failed");
> + goto cleanup_dpy;
> + }
> +
> + if (dri2_dpy->base.conn) {
> + if (!dri2_connect(dri2_dpy)) {
> + goto cleanup_conn;
> + }
> + }
> +
> + extensions = dri2_load_driver(disp);
> + if (extensions == NULL)
> + goto cleanup_conn;
> +
> + if (!dri2_bind_extensions((struct dri2_egl_display *)dri2_dpy, dri2_driver_extensions, extensions)) {
> + goto cleanup_driver;
> + }
> +
> + dri2_dpy->base.base.fd = open(dri2_dpy->device_name, O_RDWR);
> + if (dri2_dpy->base.base.fd == -1) {
> + _eglLog(_EGL_WARNING,
> + "DRI2: could not open %s (%s)", dri2_dpy->device_name,
> + strerror(errno));
> + goto cleanup_driver;
> + }
> +
> + if (dri2_dpy->base.conn) {
> + if (!dri2_authenticate(dri2_dpy)) {
> + goto cleanup_fd;
> + }
> + }
> +
> + if (dri2_dpy->dri2_minor >= 1) {
> + dri2_dpy->base.base.dri2_loader_extension.base.name = __DRI_DRI2_LOADER;
> + dri2_dpy->base.base.dri2_loader_extension.base.version = 3;
> + dri2_dpy->base.base.dri2_loader_extension.getBuffers = dri2_get_buffers;
> + dri2_dpy->base.base.dri2_loader_extension.flushFrontBuffer = dri2_flush_front_buffer;
> + dri2_dpy->base.base.dri2_loader_extension.getBuffersWithFormat =
> + dri2_get_buffers_with_format;
> + } else {
> + dri2_dpy->base.base.dri2_loader_extension.base.name = __DRI_DRI2_LOADER;
> + dri2_dpy->base.base.dri2_loader_extension.base.version = 2;
> + dri2_dpy->base.base.dri2_loader_extension.getBuffers = dri2_get_buffers;
> + dri2_dpy->base.base.dri2_loader_extension.flushFrontBuffer = dri2_flush_front_buffer;
> + dri2_dpy->base.base.dri2_loader_extension.getBuffersWithFormat = NULL;
> + }
> +
> + dri2_dpy->base.base.extensions[0] = &dri2_dpy->base.base.dri2_loader_extension.base;
> + dri2_dpy->base.base.extensions[1] = &image_lookup_extension.base;
> + dri2_dpy->base.base.extensions[2] = NULL;
> +
> + if (!dri2_create_screen(disp))
> + goto cleanup_fd;
> +
> + if (dri2_dpy->base.conn) {
> + if (!dri2_add_configs_for_visuals((struct dri2_egl_x11_display *)dri2_dpy, disp, 1))
> + goto cleanup_configs;
> + }
> +
> + disp->Extensions.MESA_drm_image = EGL_TRUE;
> + disp->Extensions.KHR_image_base = EGL_TRUE;
> + disp->Extensions.KHR_image_pixmap = EGL_TRUE;
> + disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE;
> + disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE;
> + disp->Extensions.NOK_swap_region = EGL_TRUE;
> + disp->Extensions.NOK_texture_from_pixmap = EGL_TRUE;
> +
> + /* we're supporting EGL 1.4 */
> + *major = 1;
> + *minor = 4;
> +
> + dri2_x11_dri2_initialize_driver(drv);
> +
> + return EGL_TRUE;
> +
> + cleanup_configs:
> + _eglCleanupDisplay(disp);
> + dri2_dpy->base.base.core->destroyScreen(dri2_dpy->base.base.dri_screen);
> + cleanup_fd:
> + close(dri2_dpy->base.base.fd);
> + cleanup_driver:
> + dlclose(dri2_dpy->base.base.driver);
> + cleanup_conn:
> + if (disp->PlatformDisplay == NULL)
> + xcb_disconnect(dri2_dpy->base.conn);
> + cleanup_dpy:
> + free(dri2_dpy);
> +
> + return EGL_FALSE;
> +}
> +
> diff --git a/src/egl/drivers/dri2/x11_shared.c b/src/egl/drivers/dri2/x11_shared.c
> new file mode 100644
> index 0000000..9c0df13
> --- /dev/null
> +++ b/src/egl/drivers/dri2/x11_shared.c
> @@ -0,0 +1,132 @@
> +/*
> + * 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 at bitplanet.net>
> + */
> +
> +#include "x11_shared.h"
> +
> +EGLBoolean
> +dri2_add_configs_for_visuals(struct dri2_egl_x11_display *dri2_dpy,
> + _EGLDisplay *disp, int accel)
> +{
> + xcb_screen_iterator_t s;
> + xcb_depth_iterator_t d;
> + xcb_visualtype_t *visuals;
> + int i, j, id;
> + struct dri2_egl_config *conf;
> + EGLint surface_type;
> +
> + if (xcb_connection_has_error(dri2_dpy->conn)) {
> + _eglLog(_EGL_WARNING, "xcb connection error");
> + }
> +
> + s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn));
> + d = xcb_screen_allowed_depths_iterator(s.data);
> + id = 1;
> +
> + surface_type =
> + EGL_WINDOW_BIT |
> + EGL_PIXMAP_BIT |
> + EGL_PBUFFER_BIT |
> + EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
> +
> + while (d.rem > 0) {
> + EGLBoolean class_added[6] = { 0, };
> +
> + visuals = xcb_depth_visuals(d.data);
> + for (i = 0; i < xcb_depth_visuals_length(d.data); i++) {
> + if (class_added[visuals[i]._class])
> + continue;
> +
> + class_added[visuals[i]._class] = EGL_TRUE;
> + for (j = 0; dri2_dpy->base.driver_configs[j]; j++) {
> + conf = dri2_add_config(disp, dri2_dpy->base.driver_configs[j],
> + id++, d.data->depth, surface_type, accel);
> + if (conf == NULL)
> + continue;
> + _eglSetConfigKey(&conf->base,
> + EGL_NATIVE_VISUAL_ID, visuals[i].visual_id);
> + _eglSetConfigKey(&conf->base,
> + EGL_NATIVE_VISUAL_TYPE, visuals[i]._class);
> + }
> + }
> +
> + xcb_depth_next(&d);
> + }
> +
> + if (!_eglGetArraySize(disp->Configs)) {
> + _eglLog(_EGL_WARNING, "DRI2: failed to create any config");
> + return EGL_FALSE;
> + }
> +
> + return EGL_TRUE;
> +}
> +
> +EGLBoolean
> +dri2_copy_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
> + EGLNativePixmapType target)
> +{
> + struct dri2_egl_x11_display *dri2_dpy = dri2_egl_x11_display(disp);
> + struct dri2_egl_x11_surface *dri2_surf = dri2_egl_x11_surface(surf);
> + xcb_gcontext_t gc;
> +
> + if (dri2_dpy->base.flush) {
> + (*dri2_dpy->base.flush->flush)(dri2_surf->base.dri_drawable);
> + }
> +
> + gc = xcb_generate_id(dri2_dpy->conn);
> + xcb_create_gc(dri2_dpy->conn, gc, target, 0, NULL);
> + xcb_copy_area(dri2_dpy->conn,
> + dri2_surf->drawable,
> + target,
> + gc,
> + 0, 0,
> + 0, 0,
> + dri2_surf->base.base.Width,
> + dri2_surf->base.base.Height);
> + xcb_free_gc(dri2_dpy->conn, gc);
> +
> + return EGL_TRUE;
> +}
> +
> +EGLBoolean
> +dri2_initialize_x11(_EGLDriver *drv, _EGLDisplay *disp,
> + EGLint *major, EGLint *minor)
> +{
> + EGLBoolean initialized = EGL_TRUE;
> +
> + int x11_dri2_accel = (getenv("LIBGL_ALWAYS_SOFTWARE") == NULL);
> +
> + if (x11_dri2_accel) {
> + if (!dri2_initialize_x11_dri2(drv, disp, major, minor)) {
> + initialized = dri2_initialize_x11_swrast(drv, disp, major, minor);
> + }
> + } else {
> + initialized = dri2_initialize_x11_swrast(drv, disp, major, minor);
> + }
> +
> + return initialized;
> +}
> +
> diff --git a/src/egl/drivers/dri2/x11_shared.h b/src/egl/drivers/dri2/x11_shared.h
> new file mode 100644
> index 0000000..4c6d8ae
> --- /dev/null
> +++ b/src/egl/drivers/dri2/x11_shared.h
> @@ -0,0 +1,81 @@
> +/*
> + * 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 at bitplanet.net>
> + */
> +
> +#ifndef X11_SHARED_INCLUDED
> +#define X11_SHARED_INCLUDED
> +
> +#include "egl_dri2.h"
> +#include <xcb/xcb.h>
> +#include <xcb/xfixes.h>
> +#include <X11/Xlib-xcb.h>
> +
> +struct dri2_egl_x11_display
> +{
> + struct dri2_egl_display base;
> + xcb_connection_t *conn;
> +};
> +
> +struct dri2_egl_x11_surface
> +{
> + struct dri2_egl_surface base;
> + xcb_drawable_t drawable;
> +};
> +
> +_EGL_DRIVER_TYPECAST(dri2_egl_x11_display, _EGLDisplay, obj->DriverData)
> +_EGL_DRIVER_TYPECAST(dri2_egl_x11_surface, _EGLSurface, obj)
> +
> +_EGLSurface *
> +dri2_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp,
> + _EGLConfig *conf, EGLNativeWindowType window,
> + const EGLint *attrib_list);
> +_EGLSurface *
> +dri2_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *disp,
> + _EGLConfig *conf, EGLNativePixmapType pixmap,
> + const EGLint *attrib_list);
> +
> +_EGLSurface *
> +dri2_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *disp,
> + _EGLConfig *conf, const EGLint *attrib_list);
> +
> +EGLBoolean
> +dri2_copy_buffers(_EGLDriver *drv, _EGLDisplay *disp,
> + _EGLSurface *surf, EGLNativePixmapType target);
> +
> +EGLBoolean
> +dri2_add_configs_for_visuals(struct dri2_egl_x11_display *dri2_dpy,
> + _EGLDisplay *disp, int accel);
> +
> +EGLBoolean
> +dri2_initialize_x11_swrast(_EGLDriver *drv, _EGLDisplay *disp,
> + EGLint *major, EGLint *minor);
> +
> +EGLBoolean
> +dri2_initialize_x11_dri2(_EGLDriver *drv, _EGLDisplay *disp,
> + EGLint *major, EGLint *minor);
> +
> +#endif
> +
> diff --git a/src/egl/drivers/dri2/x11_swrast.c b/src/egl/drivers/dri2/x11_swrast.c
> new file mode 100644
> index 0000000..84e6494
> --- /dev/null
> +++ b/src/egl/drivers/dri2/x11_swrast.c
> @@ -0,0 +1,486 @@
> +/*
> + * 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 at bitplanet.net>
> + * Haitao Feng <haitao.feng at intel.com>
> + */
> +
> +#include "x11_shared.h"
> +
> +struct dri2_egl_x11_swrast_surface
> +{
> + struct dri2_egl_x11_surface base;
> + int depth;
> + int bytes_per_pixel;
> + xcb_gcontext_t gc;
> + xcb_gcontext_t swapgc;
> +};
> +
> +_EGL_DRIVER_TYPECAST(dri2_egl_x11_swrast_surface, _EGLSurface, obj)
> +
> +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) },
> + { NULL }
> +};
> +
> +static struct dri2_extension_match swrast_core_extensions[] = {
> + { __DRI_TEX_BUFFER, 2, offsetof(struct dri2_egl_display, tex_buffer) },
> + { NULL }
> +};
> +
> +static void
> +swrastCreateDrawable(struct dri2_egl_x11_display * dri2_dpy,
> + struct dri2_egl_x11_swrast_surface * dri2_surf,
> + int depth)
> +{
> + uint32_t mask;
> + const uint32_t function = GXcopy;
> + uint32_t valgc[2];
> +
> + /* create GC's */
> + dri2_surf->gc = xcb_generate_id(dri2_dpy->conn);
> + mask = XCB_GC_FUNCTION;
> + xcb_create_gc(dri2_dpy->conn, dri2_surf->gc, dri2_surf->base.drawable, mask, &function);
> +
> + dri2_surf->swapgc = xcb_generate_id(dri2_dpy->conn);
> + mask = XCB_GC_FUNCTION | XCB_GC_GRAPHICS_EXPOSURES;
> + valgc[0] = function;
> + valgc[1] = False;
> + xcb_create_gc(dri2_dpy->conn, dri2_surf->swapgc, dri2_surf->base.drawable, mask, valgc);
> + dri2_surf->depth = depth;
> + switch (depth) {
> + case 32:
> + case 24:
> + dri2_surf->bytes_per_pixel = 4;
> + break;
> + case 16:
> + dri2_surf->bytes_per_pixel = 2;
> + break;
> + case 8:
> + dri2_surf->bytes_per_pixel = 1;
> + break;
> + case 0:
> + dri2_surf->bytes_per_pixel = 0;
> + break;
> + default:
> + _eglLog(_EGL_WARNING, "unsupported depth %d", depth);
> + }
> +}
> +
> +static void
> +swrastDestroyDrawable(struct dri2_egl_x11_display * dri2_dpy,
> + struct dri2_egl_x11_swrast_surface * dri2_surf)
> +{
> + xcb_free_gc(dri2_dpy->conn, dri2_surf->gc);
> + xcb_free_gc(dri2_dpy->conn, dri2_surf->swapgc);
> +}
> +
> +static void
> +swrastGetDrawableInfo(__DRIdrawable * draw,
> + int *x, int *y, int *w, int *h,
> + void *loaderPrivate)
> +{
> + struct dri2_egl_x11_swrast_surface *dri2_surf = loaderPrivate;
> + struct dri2_egl_x11_display *dri2_dpy =
> + dri2_egl_x11_display(dri2_surf->base.base.base.Resource.Display);
> +
> + xcb_get_geometry_cookie_t cookie;
> + xcb_get_geometry_reply_t *reply;
> + xcb_generic_error_t *error;
> +
> + *w = *h = 0;
> + cookie = xcb_get_geometry (dri2_dpy->conn, dri2_surf->base.drawable);
> + reply = xcb_get_geometry_reply (dri2_dpy->conn, cookie, &error);
> + if (reply == NULL)
> + return;
> +
> + if (error != NULL) {
> + _eglLog(_EGL_WARNING, "error in xcb_get_geometry");
> + free(error);
> + } else {
> + *w = reply->width;
> + *h = reply->height;
> + }
> + free(reply);
> +}
> +
> +static void
> +swrastPutImage(__DRIdrawable * draw, int op,
> + int x, int y, int w, int h,
> + char *data, void *loaderPrivate)
> +{
> + struct dri2_egl_x11_swrast_surface *dri2_surf = loaderPrivate;
> + struct dri2_egl_x11_display *dri2_dpy =
> + dri2_egl_x11_display(dri2_surf->base.base.base.Resource.Display);
> +
> + xcb_gcontext_t gc;
> +
> + switch (op) {
> + case __DRI_SWRAST_IMAGE_OP_DRAW:
> + gc = dri2_surf->gc;
> + break;
> + case __DRI_SWRAST_IMAGE_OP_SWAP:
> + gc = dri2_surf->swapgc;
> + break;
> + default:
> + return;
> + }
> +
> + xcb_put_image(dri2_dpy->conn, XCB_IMAGE_FORMAT_Z_PIXMAP, dri2_surf->base.drawable,
> + gc, w, h, x, y, 0, dri2_surf->depth,
> + w*h*dri2_surf->bytes_per_pixel, (const uint8_t *)data);
> +}
> +
> +static void
> +swrastGetImage(__DRIdrawable * read,
> + int x, int y, int w, int h,
> + char *data, void *loaderPrivate)
> +{
> + struct dri2_egl_x11_swrast_surface *dri2_surf = loaderPrivate;
> + struct dri2_egl_x11_display *dri2_dpy =
> + dri2_egl_x11_display(dri2_surf->base.base.base.Resource.Display);
> +
> + xcb_get_image_cookie_t cookie;
> + xcb_get_image_reply_t *reply;
> + xcb_generic_error_t *error;
> +
> + cookie = xcb_get_image (dri2_dpy->conn, XCB_IMAGE_FORMAT_Z_PIXMAP,
> + dri2_surf->base.drawable, x, y, w, h, ~0);
> + reply = xcb_get_image_reply (dri2_dpy->conn, cookie, &error);
> + if (reply == NULL)
> + return;
> +
> + if (error != NULL) {
> + _eglLog(_EGL_WARNING, "error in xcb_get_image");
> + free(error);
> + } else {
> + uint32_t bytes = xcb_get_image_data_length(reply);
> + uint8_t *idata = xcb_get_image_data(reply);
> + memcpy(data, idata, bytes);
> + }
> + free(reply);
> +}
> +
> +static EGLBoolean
> +dri2_x11_swrast_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
> +{
> + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
> + struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
> +
> + (dri2_dpy->core->swapBuffers) (dri2_surf->dri_drawable);
> +
> + return EGL_TRUE;
> +}
> +
> +static EGLBoolean
> +dri2_create_x11_swrast_screen(_EGLDisplay *disp)
> +{
> + const __DRIextension **extensions;
> + struct dri2_egl_display *dri2_dpy;
> + unsigned int api_mask;
> +
> + dri2_dpy = disp->DriverData;
> +
> + dri2_dpy->dri_screen =
> + dri2_dpy->swrast->createNewScreen(0, dri2_dpy->extensions,
> + &dri2_dpy->driver_configs, disp);
> +
> + if (dri2_dpy->dri_screen == NULL) {
> + _eglLog(_EGL_WARNING, "DRI2: failed to create dri screen");
> + return EGL_FALSE;
> + }
> +
> + extensions = dri2_dpy->core->getExtensions(dri2_dpy->dri_screen);
> + if (!dri2_bind_extensions((struct dri2_egl_display *)dri2_dpy, swrast_core_extensions, extensions))
> + goto cleanup_dri_screen;
> +
> + if (dri2_dpy->swrast->base.version >= 2)
> + api_mask = 1 << __DRI_API_OPENGL | 1 << __DRI_API_GLES | 1 << __DRI_API_GLES2;
> + else
> + api_mask = 1 << __DRI_API_OPENGL;
> +
> + disp->ClientAPIsMask = 0;
> + if (api_mask & (1 <<__DRI_API_OPENGL))
> + disp->ClientAPIsMask |= EGL_OPENGL_BIT;
> + if (api_mask & (1 <<__DRI_API_GLES))
> + disp->ClientAPIsMask |= EGL_OPENGL_ES_BIT;
> + if (api_mask & (1 << __DRI_API_GLES2))
> + disp->ClientAPIsMask |= EGL_OPENGL_ES2_BIT;
> +
> + if (dri2_dpy->swrast->base.version >= 2) {
> + disp->Extensions.KHR_surfaceless_gles1 = EGL_TRUE;
> + disp->Extensions.KHR_surfaceless_gles2 = EGL_TRUE;
> + disp->Extensions.KHR_surfaceless_opengl = EGL_TRUE;
> + }
> +
> + return EGL_TRUE;
> +
> +cleanup_dri_screen:
> + dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
> +
> + return EGL_FALSE;
> +}
> +
> +/**
> + * Called via eglTerminate(), drv->API.Terminate().
> + */
> +static EGLBoolean
> +dri2_x11_swrast_terminate(_EGLDriver *drv, _EGLDisplay *disp)
> +{
> + struct dri2_egl_x11_display *dri2_dpy = dri2_egl_x11_display(disp);
> +
> + _eglReleaseDisplayResources(drv, disp);
> + _eglCleanupDisplay(disp);
> +
> + dri2_dpy->base.core->destroyScreen(dri2_dpy->base.dri_screen);
> + dlclose(dri2_dpy->base.driver);
> + if (disp->PlatformDisplay == NULL)
> + xcb_disconnect(dri2_dpy->conn);
> + free(dri2_dpy);
> + disp->DriverData = NULL;
> +
> + return EGL_TRUE;
> +}
> +
> +static _EGLSurface *
> +dri2_x11_swrast_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
> + _EGLConfig *conf, EGLNativeWindowType window,
> + const EGLint *attrib_list)
> +{
> + struct dri2_egl_x11_display *dri2_dpy = dri2_egl_x11_display(disp);
> + struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
> + struct dri2_egl_x11_swrast_surface *dri2_surf;
> + xcb_get_geometry_cookie_t cookie;
> + xcb_get_geometry_reply_t *reply;
> + xcb_screen_iterator_t s;
> + xcb_generic_error_t *error;
> +
> + dri2_surf = malloc(sizeof *dri2_surf);
> + if (!dri2_surf) {
> + _eglError(EGL_BAD_ALLOC, "dri2_create_surface");
> + return NULL;
> + }
> +
> + if (!_eglInitSurface(&dri2_surf->base.base.base, disp, type, conf, attrib_list))
> + goto cleanup_surf;
> +
> + if (type == EGL_PBUFFER_BIT) {
> + dri2_surf->base.drawable = xcb_generate_id(dri2_dpy->conn);
> + s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn));
> + xcb_create_pixmap(dri2_dpy->conn,
> + _eglGetConfigKey(conf, EGL_BUFFER_SIZE),
> + dri2_surf->base.drawable, s.data->root,
> + dri2_surf->base.base.base.Width, dri2_surf->base.base.base.Height);
> + } else {
> + dri2_surf->base.drawable = window;
> + }
> +
> + dri2_surf->base.base.dri_drawable =
> + (*dri2_dpy->base.swrast->createNewDrawable) (dri2_dpy->base.dri_screen,
> + dri2_conf->dri_config, dri2_surf);
> +
> + if (dri2_surf->base.base.dri_drawable == NULL) {
> + _eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable");
> + goto cleanup_pixmap;
> + }
> +
> + swrastCreateDrawable(dri2_dpy, dri2_surf, _eglGetConfigKey(conf, EGL_DEPTH_SIZE));
> +
> + if (type != EGL_PBUFFER_BIT) {
> + cookie = xcb_get_geometry (dri2_dpy->conn, dri2_surf->base.drawable);
> + reply = xcb_get_geometry_reply (dri2_dpy->conn, cookie, &error);
> + if (reply == NULL || error != NULL) {
> + _eglError(EGL_BAD_ALLOC, "xcb_get_geometry");
> + free(error);
> + goto cleanup_dri_drawable;
> + }
> +
> + dri2_surf->base.base.base.Width = reply->width;
> + dri2_surf->base.base.base.Height = reply->height;
> + free(reply);
> + }
> +
> + return &dri2_surf->base.base.base;
> +
> + cleanup_dri_drawable:
> + dri2_dpy->base.core->destroyDrawable(dri2_surf->base.base.dri_drawable);
> + cleanup_pixmap:
> + if (type == EGL_PBUFFER_BIT)
> + xcb_free_pixmap(dri2_dpy->conn, dri2_surf->base.drawable);
> + cleanup_surf:
> + free(dri2_surf);
> +
> + return NULL;
> +}
> +
> +/**
> + * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
> + */
> +static _EGLSurface *
> +dri2_x11_swrast_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp,
> + _EGLConfig *conf, EGLNativeWindowType window,
> + const EGLint *attrib_list)
> +{
> + return dri2_x11_swrast_create_surface(drv, disp, EGL_WINDOW_BIT, conf,
> + window, attrib_list);
> +}
> +
> +static _EGLSurface *
> +dri2_x11_swrast_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *disp,
> + _EGLConfig *conf, EGLNativePixmapType pixmap,
> + const EGLint *attrib_list)
> +{
> + return dri2_x11_swrast_create_surface(drv, disp, EGL_PIXMAP_BIT, conf,
> + pixmap, attrib_list);
> +}
> +
> +static _EGLSurface *
> +dri2_x11_swrast_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *disp,
> + _EGLConfig *conf, const EGLint *attrib_list)
> +{
> + return dri2_x11_swrast_create_surface(drv, disp, EGL_PBUFFER_BIT, conf,
> + XCB_WINDOW_NONE, attrib_list);
> +}
> +
> +static EGLBoolean
> +dri2_x11_swrast_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
> +{
> + struct dri2_egl_x11_display *dri2_dpy = dri2_egl_x11_display(disp);
> + struct dri2_egl_x11_swrast_surface *dri2_surf = dri2_egl_x11_swrast_surface(surf);
> +
> + if (_eglIsSurfaceBound(surf))
> + return EGL_TRUE;
> +
> + (*dri2_dpy->base.core->destroyDrawable)(dri2_surf->base.base.dri_drawable);
> +
> + swrastDestroyDrawable(dri2_dpy, dri2_surf);
> +
> + if (surf->Type == EGL_PBUFFER_BIT)
> + xcb_free_pixmap (dri2_dpy->conn, dri2_surf->base.drawable);
> +
> + free(surf);
> +
> + return EGL_TRUE;
> +}
> +
> +static void
> +dri2_x11_swrast_initialize_driver(_EGLDriver *drv)
> +{
> + struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
> +
> + dri2_drv->base.API.Terminate = dri2_x11_swrast_terminate;
> + dri2_drv->base.API.CreateWindowSurface = dri2_x11_swrast_create_window_surface;
> + dri2_drv->base.API.CreatePixmapSurface = dri2_x11_swrast_create_pixmap_surface;
> + dri2_drv->base.API.CreatePbufferSurface = dri2_x11_swrast_create_pbuffer_surface;
> + dri2_drv->base.API.DestroySurface = dri2_x11_swrast_destroy_surface;
> + dri2_drv->base.API.SwapBuffers = dri2_x11_swrast_swap_buffers;
> + dri2_drv->base.API.CopyBuffers = dri2_copy_buffers;
> +
> +/**
> + * Currently un-supported functions:
> + * SwapBuffersRegionNOK
> + * CreateImageKHR, DestroyImageKHR, CreateDRMImageMESA, ExportDRMImageMESA
> +*/
> +
> + dri2_drv->base.Name = "DRI2_X11_SWRAST";
> +}
> +
> +EGLBoolean
> +dri2_initialize_x11_swrast(_EGLDriver *drv, _EGLDisplay *disp,
> + EGLint *major, EGLint *minor)
> +{
> + struct dri2_egl_x11_display *dri2_dpy;
> + const __DRIextension **extensions;
> +
> + dri2_dpy = malloc(sizeof *dri2_dpy);
> + if (!dri2_dpy)
> + return _eglError(EGL_BAD_ALLOC, "eglInitialize");
> +
> + memset(dri2_dpy, 0, sizeof *dri2_dpy);
> +
> + disp->DriverData = (void *) dri2_dpy;
> + if (disp->PlatformDisplay == NULL) {
> + dri2_dpy->conn = xcb_connect(0, 0);
> + } else {
> + dri2_dpy->conn = XGetXCBConnection((Display *) disp->PlatformDisplay);
> + }
> +
> + if (xcb_connection_has_error(dri2_dpy->conn)) {
> + _eglLog(_EGL_WARNING, "DRI2: xcb_connect failed");
> + goto cleanup_dpy;
> + }
> +
> + dri2_dpy->base.driver_name = dri2_strndup("swrast", strlen("swrast"));
> +
> + extensions = dri2_load_driver(disp);
> +
> + if (extensions == NULL)
> + goto cleanup_conn;
> +
> + if (!dri2_bind_extensions((struct dri2_egl_display *)dri2_dpy,
> + swrast_driver_extensions, extensions)) {
> + goto cleanup_driver;
> + }
> +
> + dri2_dpy->base.swrast_loader_extension.base.name = __DRI_SWRAST_LOADER;
> + dri2_dpy->base.swrast_loader_extension.base.version = __DRI_SWRAST_LOADER_VERSION;
> + dri2_dpy->base.swrast_loader_extension.getDrawableInfo = swrastGetDrawableInfo;
> + dri2_dpy->base.swrast_loader_extension.putImage = swrastPutImage;
> + dri2_dpy->base.swrast_loader_extension.getImage = swrastGetImage;
> +
> + dri2_dpy->base.extensions[0] = &dri2_dpy->base.swrast_loader_extension.base;
> + dri2_dpy->base.extensions[1] = NULL;
> + dri2_dpy->base.extensions[2] = NULL;
> +
> + if (!dri2_create_x11_swrast_screen(disp))
> + goto cleanup_driver;
> +
> + if (dri2_dpy->conn) {
> + if (!dri2_add_configs_for_visuals(dri2_dpy, disp, 0))
> + goto cleanup_configs;
> + }
> +
> + /* we're supporting EGL 1.4 */
> + *major = 1;
> + *minor = 4;
> +
> + dri2_x11_swrast_initialize_driver(drv);
> +
> + return EGL_TRUE;
> +
> + cleanup_configs:
> + _eglCleanupDisplay(disp);
> + dri2_dpy->base.core->destroyScreen(dri2_dpy->base.dri_screen);
> + cleanup_driver:
> + dlclose(dri2_dpy->base.driver);
> + cleanup_conn:
> + if (disp->PlatformDisplay == NULL)
> + xcb_disconnect(dri2_dpy->conn);
> + cleanup_dpy:
> + free(dri2_dpy);
> +
> + return EGL_FALSE;
> +}
> +
> --
> 1.7.2.2
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev
>
More information about the mesa-dev
mailing list