[PATCH 2/2] egl_dri2: Adding swrast and refactoring
Haitao Feng
haitao.feng at intel.com
Sat Jan 29 23:50:01 PST 2011
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.
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
More information about the mesa-dev
mailing list