[pkg-fso-commits] [SCM] xf86-video-glamo, SMedia Glamo video driver for X.Org branch, master, updated. upstream/0.0.0+20090707.git98c012f7-57-g9918e08

Thomas White taw at bitwiz.org.uk
Fri Jan 8 13:24:38 UTC 2010


The following commit has been merged in the master branch:
commit 477353734de273195ee777eeace44f50aab00e47
Author: Thomas White <taw at bitwiz.org.uk>
Date:   Wed Jul 22 17:29:18 2009 +0100

    Drop in most of the rest of the code

diff --git a/src/Makefile.am b/src/Makefile.am
index 28da384..447784f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -38,4 +38,6 @@ glamo_drv_la_SOURCES = \
          glamo-engine.c \
          glamo-kms-driver.c \
          crtc.c \
-         output.c
+         output.c \
+         glamo-dri2.c \
+         glamo-kms-exa.c
diff --git a/src/glamo-dri2.c b/src/glamo-dri2.c
new file mode 100644
index 0000000..fccf2ed
--- /dev/null
+++ b/src/glamo-dri2.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * 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, sub license, 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 NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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.
+ *
+ *
+ * Author: Alan Hourihane <alanh at tungstengraphics.com>
+ *
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+
+#include "driver.h"
+
+#include "dri2.h"
+
+extern unsigned int
+driGetPixmapHandle(PixmapPtr pPixmap, unsigned int *flags);
+
+void
+driLock(ScreenPtr pScreen)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    GlamoPtr pGlamo = GlamoPTR(pScrn);
+
+    if (!pGlamo->lock_held)
+	DRM_LOCK(pGlamo->drm_fd, pGlamo->lock, pGlamo->context, 0);
+
+    pGlamo->lock_held = 1;
+}
+
+void
+driUnlock(ScreenPtr pScreen)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    GlamoPtr pGlamo = GlamoPTR(pScrn);
+
+    if (pGlamo->lock_held)
+	DRM_UNLOCK(pGlamo->drm_fd, pGlamo->lock, pGlamo->context);
+
+    pGlamo->lock_held = 0;
+}
+
+static void
+driBeginClipNotify(ScreenPtr pScreen)
+{
+    driLock(pScreen);
+}
+
+static void
+driEndClipNotify(ScreenPtr pScreen)
+{
+    driUnlock(pScreen);
+}
+
+struct __DRILock
+{
+    unsigned int block_header;
+    drm_hw_lock_t lock;
+    unsigned int next_id;
+};
+
+#define DRI2_SAREA_BLOCK_HEADER(type, size) (((type) << 16) | (size))
+#define DRI2_SAREA_BLOCK_LOCK		0x0001
+
+void
+driScreenInit(ScreenPtr pScreen)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    GlamoPtr pGlamo = GlamoPTR(pScrn);
+    DRI2InfoRec dri2info;
+    const char *driverName;
+    unsigned int sarea_handle;
+    struct __DRILock *DRILock;
+    void *p;
+
+    dri2info.version = 1;
+    dri2info.fd = pGlamo->drm_fd;
+    dri2info.driverSareaSize = sizeof(struct __DRILock);
+    dri2info.driverName = "i915";      /* FIXME */
+    dri2info.getPixmapHandle = driGetPixmapHandle;
+    dri2info.beginClipNotify = driBeginClipNotify;
+    dri2info.endClipNotify = driEndClipNotify;
+
+    p = DRI2ScreenInit(pScreen, &dri2info);
+    if (!p)
+	return;
+
+    DRILock = p;
+    DRILock->block_header =
+	DRI2_SAREA_BLOCK_HEADER(DRI2_SAREA_BLOCK_LOCK, sizeof *DRILock);
+    pGlamo->lock = &DRILock->lock;
+    pGlamo->context = 1;
+    DRILock->next_id = 2;
+    driLock(pScreen);
+
+    DRI2Connect(pScreen, &pGlamo->drm_fd, &driverName, &sarea_handle);
+}
+
+void
+driCloseScreen(ScreenPtr pScreen)
+{
+    driUnlock(pScreen);
+    DRI2CloseScreen(pScreen);
+}
diff --git a/src/glamo-kms-driver.c b/src/glamo-kms-driver.c
index c04a62f..1d9bac8 100644
--- a/src/glamo-kms-driver.c
+++ b/src/glamo-kms-driver.c
@@ -53,6 +53,7 @@
 
 #include <sys/types.h>
 #include <dirent.h>
+#include <stdint.h>
 
 #include <xorg-server.h>
 #include <drm.h>
@@ -66,6 +67,8 @@
 #include "xf86drm.h"
 
 #include "glamo.h"
+#include "glamo-kms-driver.h"
+#include "glamo-kms-exa.h"
 
 
 static const char *fbSymbols[] = {
@@ -103,37 +106,68 @@ Bool GlamoKernelModesettingAvailable()
 }
 
 
-static Bool crtc_resize(ScrnInfoPtr pScrn, int width, int height)
+static Bool CreateFrontBuffer(ScrnInfoPtr pScrn)
 {
-#if 0
-    modesettingPtr ms = modesettingPTR(pScrn);
-    ScreenPtr pScreen = pScrn->pScreen;
-    PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);
-    Bool fbAccessDisabled;
-    CARD8 *fbstart;
-
-    if (width == pScrn->virtualX && height == pScrn->virtualY)
+	GlamoPtr pGlamo = GlamoPTR(pScrn);
+	ScreenPtr pScreen = pScrn->pScreen;
+	PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);
+	Bool fbAccessDisabled;
+	int flags;
+
+	pGlamo->noEvict = TRUE;
+	pScreen->ModifyPixmapHeader(rootPixmap,
+	                            pScrn->virtualX, pScrn->virtualY,
+	                            pScrn->depth, pScrn->bitsPerPixel,
+	                            pScrn->displayWidth * pScrn->bitsPerPixel/8,
+	                            NULL);
+	pGlamo->noEvict = FALSE;
+
+	drmModeAddFB(ms->fd,
+	             pScrn->virtualX,
+	             pScrn->virtualY,
+	             pScrn->depth,
+	             pScrn->bitsPerPixel,
+	             pScrn->displayWidth * pScrn->bitsPerPixel / 8,
+	             driGetPixmapHandle(rootPixmap, &flags), &ms->fb_id);
+
+	pScrn->frameX0 = 0;
+	pScrn->frameY0 = 0;
+	GlamoKMSAdjustFrame(pScrn->scrnIndex,
+	                    pScrn->frameX0, pScrn->frameY0,
+	                    0);
+
 	return TRUE;
+}
 
-    ErrorF("RESIZING TO %dx%d\n", width, height);
 
-    pScrn->virtualX = width;
-    pScrn->virtualY = height;
+static Bool crtc_resize(ScrnInfoPtr pScrn, int width, int height)
+{
+	GlamoPtr pGlamo = GlamoPTR(pScrn);
+	ScreenPtr pScreen = pScrn->pScreen;
+	PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);
+	Bool fbAccessDisabled;
+	CARD8 *fbstart;
 
-    /* HW dependent - FIXME */
-    pScrn->displayWidth = pScrn->virtualX;
+	if ( (width == pScrn->virtualX) && (height == pScrn->virtualY) )
+		return TRUE;	/* Nothing to do */
 
-    drmModeRmFB(ms->fd, ms->fb_id);
+	ErrorF("RESIZING TO %dx%d\n", width, height);
 
-    /* now create new frontbuffer */
-    return CreateFrontBuffer(pScrn);
-#endif
-	return FALSE;
+	pScrn->virtualX = width;
+	pScrn->virtualY = height;
+
+	/* HW dependent - FIXME */
+	pScrn->displayWidth = pScrn->virtualX;
+
+	drmModeRmFB(pGlamo->drm_fd, pGlamo->fb_id);
+
+	/* now create new frontbuffer */
+	return CreateFrontBuffer(pScrn);
 }
 
 
 static const xf86CrtcConfigFuncsRec crtc_config_funcs = {
-    crtc_resize
+	crtc_resize
 };
 
 
@@ -224,33 +258,214 @@ Bool GlamoKMSPreInit(ScrnInfoPtr pScrn, int flags)
 }
 
 
+static Bool GlamoKMSCloseScreen(int scrnIndex, ScreenPtr pScreen)
+{
+	ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+	GlamoPtr pGlamo = GlamoPTR(pScrn);
+
+	if ( pScrn->vtSema ) {
+		GlamoKMSLeaveVT(scrnIndex, 0);
+	}
+	driCloseScreen(pScreen);
+
+	pScreen->CreateScreenResources = pGlamo->createScreenResources;
+
+	if ( pGlamo->exa ) {
+		ExaClose(pScrn);
+	}
+
+	drmClose(pGlamo->drm_fd);
+	pGlamo->drm_fd = -1;
+
+	pScrn->vtSema = FALSE;
+	pScreen->CloseScreen = pGlamo->CloseScreen;
+	return (*pScreen->CloseScreen)(scrnIndex, pScreen);
+}
+
+
 Bool GlamoKMSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc,
                         char **argv)
 {
+	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+	GlamoPtr pGlamo = GlamoPTR(pScrn);
+	VisualPtr visual;
+	unsigned long sys_mem;
+	int c;
+	MessageType from;
+
+	/* Deal with server regeneration */
+	if ( pGlamo->drm_fd < 0 ) {
+	pGlamo->drm_fd = drmOpen(NULL, "platform:glamo-fb");
+	if ( pGlamo->drm_fd < 0 ) return FALSE;
+	}
+
+	pScrn->pScreen = pScreen;
+
+	/* HW dependent - FIXME */
+	pScrn->displayWidth = pScrn->virtualX;
+
+	miClearVisualTypes();
+
+	if ( !miSetVisualTypes(pScrn->depth,
+	                      miGetDefaultVisualMask(pScrn->depth),
+	                      pScrn->rgbBits, pScrn->defaultVisual) ) {
+		return FALSE;
+	}
+
+	if ( !miSetPixmapDepths() ) return FALSE;
+
+	pScrn->memPhysBase = 0;
+	pScrn->fbOffset = 0;
+
+	if ( !fbScreenInit(pScreen, NULL,
+	                  pScrn->virtualX, pScrn->virtualY,
+	                  pScrn->xDpi, pScrn->yDpi,
+	                  pScrn->displayWidth, pScrn->bitsPerPixel) ) {
+		return FALSE;
+	}
+
+	if (pScrn->bitsPerPixel > 8) {
+		/* Fixup RGB ordering */
+		visual = pScreen->visuals + pScreen->numVisuals;
+		while (--visual >= pScreen->visuals) {
+			if ((visual->class | DynamicClass) == DirectColor) {
+				visual->offsetRed = pScrn->offset.red;
+				visual->offsetGreen = pScrn->offset.green;
+				visual->offsetBlue = pScrn->offset.blue;
+				visual->redMask = pScrn->mask.red;
+				visual->greenMask = pScrn->mask.green;
+				visual->blueMask = pScrn->mask.blue;
+			}
+		}
+	}
+
+	fbPictureInit(pScreen, NULL, 0);
+
+	pGlamo->createScreenResources = pScreen->CreateScreenResources;
+	pScreen->CreateScreenResources = CreateScreenResources;
+
+	xf86SetBlackWhitePixels(pScreen);
+
+	pGlamo->exa = GlamoKMSExaInit(pScrn);
+
+	miInitializeBackingStore(pScreen);
+	xf86SetBackingStore(pScreen);
+	xf86SetSilkenMouse(pScreen);
+	miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
+
+	/* Need to extend HWcursor support to handle mask interleave */
+	if (!ms->SWCursor) {
+		xf86_cursors_init(pScreen, 64, 64,
+		                  HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 |
+		                  HARDWARE_CURSOR_ARGB);
+	}
+
+	/* Must force it before EnterVT, so we are in control of VT and
+	 * later memory should be bound when allocating, e.g rotate_mem */
+	pScrn->vtSema = TRUE;
+
+	pScreen->SaveScreen = xf86SaveScreen;
+	pGlamo->CloseScreen = pScreen->CloseScreen;
+	pScreen->CloseScreen = GlamoKMSCloseScreen;
+
+	if ( !xf86CrtcScreenInit(pScreen) ) return FALSE;
+
+	if ( !miCreateDefColormap(pScreen) ) return FALSE;
+
+	xf86DPMSInit(pScreen, xf86DPMSSet, 0);
+
+	if ( serverGeneration == 1 ) {
+		xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
+	}
+
+	driScreenInit(pScreen);
+
+	return GlamoKMSEnterVT(scrnIndex, 1);
 }
 
 
-Bool GlamoSwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
+Bool GlamoKMSSwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
 {
+	ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+	return xf86SetSingleMode(pScrn, mode, RR_Rotate_0);
 }
 
 
-void GlamoAdjustFrame(int scrnIndex, int x, int y, int flags)
+void GlamoKMSAdjustFrame(int scrnIndex, int x, int y, int flags)
 {
+	ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
+	xf86OutputPtr output = config->output[config->compat_output];
+	xf86CrtcPtr crtc = output->crtc;
+
+	if (crtc && crtc->enabled) {
+		crtc->funcs->mode_set(crtc,
+		                      pScrn->currentMode,
+		                      pScrn->currentMode,
+		                      x, y);
+		crtc->x = output->initial_x + x;
+		crtc->y = output->initial_y + y;
+	}
 }
 
 
-Bool GlamoEnterVT(int scrnIndex, int flags)
+Bool GlamoKMSEnterVT(int scrnIndex, int flags)
 {
+	ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+	GlamoPtr pGlamo = GlamoPTR(pScrn);
+
+	driUnlock(pScrn->pScreen);
+
+	/* Only save state once per server generation since that's what most
+	* drivers do.  Could change this to save state at each VT enter. */
+	if ( pGlamo->SaveGeneration != serverGeneration ) {
+		pGlamo->SaveGeneration = serverGeneration;
+		/* ...except there is no hardware state to save */
+	}
+
+	if ( !flags ) {
+		/* signals startup as we'll do this in CreateScreenResources */
+		CreateFrontBuffer(pScrn);
+	}
+
+	if ( !xf86SetDesiredModes(pScrn) ) return FALSE;
+
+	return TRUE;
 }
 
 
-void GlamoLeaveVT(int scrnIndex, int flags)
+void GlamoKMSLeaveVT(int scrnIndex, int flags)
 {
+	ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+	GlamoPtr pGlamo = GlamoPTR(pScrn);
+	xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
+	int o;
+
+	for (o = 0; o < config->num_crtc; o++) {
+
+		xf86CrtcPtr crtc = config->crtc[o];
+
+		cursor_destroy(crtc);
+
+		if ( crtc->rotatedPixmap || crtc->rotatedData ) {
+			crtc->funcs->shadow_destroy(crtc, crtc->rotatedPixmap,
+			                            crtc->rotatedData);
+			crtc->rotatedPixmap = NULL;
+			crtc->rotatedData = NULL;
+		}
+
+	}
+
+	drmModeRmFB(pGlamo->drm_fd, pGlamo->fb_id);
+
+	driLock(pScrn->pScreen);
+
+	pScrn->vtSema = FALSE;
 }
 
 
-ModeStatus GlamoValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose,
+ModeStatus GlamoKMSValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose,
                      int flags)
 {
+	return MODE_OK;
 }
diff --git a/src/glamo-kms-exa.c b/src/glamo-kms-exa.c
new file mode 100644
index 0000000..6d84c59
--- /dev/null
+++ b/src/glamo-kms-exa.c
@@ -0,0 +1,872 @@
+/*
+ * EXA via DRI for the SMedia Glamo3362 X.org Driver
+ *
+ * Copyright 2009 Thomas White <taw at bitwiz.org.uk>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * The KMS parts of this driver are based on xf86-video-modesetting, to
+ * which the following notice applies:
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * 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, sub license, 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 NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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.
+ *
+ *
+ * Author: Alan Hourihane <alanh at tungstengraphics.com>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/* FIXME ! */
+#define DRI_DRIVER_PATH "/ISO/X.Org/modular/i386/lib/dri"
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "driver.h"
+#include <dlfcn.h>
+
+#include "pipe/p_winsys.h"
+#include "pipe/p_format.h"
+#include "pipe/p_context.h"
+#include "pipe/p_util.h"
+#include "pipe/p_state.h"
+#include "pipe/p_inlines.h"
+
+/* EXA winsys */
+struct exa_context
+{
+};
+
+struct exa_winsys
+{
+    struct pipe_winsys base;
+    modesettingPtr ms;
+};
+
+struct exa_buffer
+{
+    struct pipe_buffer base;
+    drmBO bo;
+    boolean userBuffer;	/** Is this a user-space buffer? */
+    //void *data;
+    //void *mapped;
+};
+
+struct exa_surface
+{
+    struct pipe_surface surface;
+};
+
+struct exa_entity
+{
+    ExaDriverPtr pExa;
+    struct exa_context *c;
+    struct pipe_winsys *ws;
+    struct pipe_context *ctx;
+    struct pipe_screen *scrn;
+};
+
+static INLINE struct exa_winsys *
+exa_get_winsys(struct pipe_winsys *ws)
+{
+    return (struct exa_winsys *)ws;
+}
+
+static INLINE struct exa_surface *
+exa_get_surface(struct pipe_surface *ps)
+{
+    return (struct exa_surface *)ps;
+}
+
+static INLINE struct exa_buffer *
+exa_get_buffer(struct pipe_buffer *buf)
+{
+    return (struct exa_buffer *)buf;
+}
+
+static void *
+exa_buffer_map(struct pipe_winsys *pws, struct pipe_buffer *buf,
+	       unsigned flags)
+{
+    struct exa_buffer *exa_buf = exa_get_buffer(buf);
+    struct exa_winsys *exa_winsys = exa_get_winsys(pws);
+    void *virtual;
+
+    drmBOMap(exa_winsys->ms->fd,
+	     &exa_buf->bo, DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0, &virtual);
+
+    return virtual;
+}
+
+static void
+exa_buffer_unmap(struct pipe_winsys *pws, struct pipe_buffer *buf)
+{
+    struct exa_buffer *exa_buf = exa_get_buffer(buf);
+    struct exa_winsys *exa_winsys = exa_get_winsys(pws);
+
+    drmBOUnmap(exa_winsys->ms->fd, &exa_buf->bo);
+}
+
+static void
+exa_buffer_destroy(struct pipe_winsys *pws, struct pipe_buffer *buf)
+{
+    struct exa_winsys *exa_winsys = exa_get_winsys(pws);
+    struct exa_buffer *exa_buf = exa_get_buffer(buf);
+
+    drmBOUnreference(exa_winsys->ms->fd, &exa_buf->bo);
+
+    free(exa_buf);
+}
+
+static void
+exa_flush_frontbuffer(struct pipe_winsys *pws,
+		      struct pipe_surface *surf, void *context_private)
+{
+    struct exa_buffer *exa_buf = exa_get_buffer(surf->buffer);
+
+    ErrorF("WANT TO FLUSH\n");
+}
+
+static const char *
+exa_get_name(struct pipe_winsys *pws)
+{
+    return "EXA";
+}
+
+static struct pipe_buffer *
+exa_buffer_create(struct pipe_winsys *pws,
+		  unsigned alignment, unsigned usage, unsigned size)
+{
+    struct exa_buffer *buffer = xcalloc(1, sizeof(struct exa_buffer));
+    struct exa_winsys *exa_winsys = exa_get_winsys(pws);
+    unsigned int flags = 0;
+
+    buffer->base.refcount = 1;
+    buffer->base.alignment = alignment;
+    buffer->base.usage = usage;
+    buffer->base.size = size;
+
+    if (exa_winsys->ms->noEvict) {
+	flags = DRM_BO_FLAG_NO_EVICT;
+	ErrorF("DISPLAY TARGET\n");
+    }
+
+    ErrorF("SIZE %d %d\n", size, alignment);
+    if (!buffer->bo.handle) {
+	// buffer->data = align_malloc(size, alignment);
+	drmBOCreate(exa_winsys->ms->fd, size, 0, NULL,
+		    DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE |
+		    DRM_BO_FLAG_SHAREABLE | DRM_BO_FLAG_MEM_TT |
+		    DRM_BO_FLAG_MAPPABLE | flags,
+		    0, &buffer->bo);
+    }
+
+    return &buffer->base;
+}
+
+static struct pipe_buffer *
+exa_user_buffer_create(struct pipe_winsys *pws, void *ptr, unsigned bytes)
+{
+    struct exa_buffer *buffer = xcalloc(1, sizeof(struct exa_buffer));
+
+    buffer->base.refcount = 1;
+    buffer->base.size = bytes;
+    buffer->userBuffer = TRUE;
+    //buffer->data = ptr;
+    ErrorF("USERBUFFER\n");
+
+    return &buffer->base;
+}
+
+/**
+ * Round n up to next multiple.
+ */
+static INLINE unsigned
+round_up(unsigned n, unsigned multiple)
+{
+    return (n + multiple - 1) & ~(multiple - 1);
+}
+
+static int
+exa_surface_alloc_storage(struct pipe_winsys *winsys,
+			  struct pipe_surface *surf,
+			  unsigned width, unsigned height,
+			  enum pipe_format format,
+			  unsigned flags, unsigned tex_usage)
+{
+    const unsigned alignment = 64;
+
+    surf->width = width;
+    surf->height = height;
+    surf->format = format;
+    pf_get_block(format, &surf->block);
+    surf->stride = round_up(surf->nblocksx * surf->block.size, alignment);
+
+    assert(!surf->buffer);
+    surf->buffer = winsys->buffer_create(winsys, alignment,
+					 PIPE_BUFFER_USAGE_PIXEL,
+					 surf->stride * height);
+    if (!surf->buffer)
+	return -1;
+
+    return 0;
+}
+
+/**
+ * Called via winsys->surface_alloc() to create new surfaces.
+ */
+static struct pipe_surface *
+exa_surface_alloc(struct pipe_winsys *ws)
+{
+    struct exa_surface *wms = xcalloc(1, sizeof(struct exa_surface));
+
+    assert(ws);
+
+    wms->surface.refcount = 1;
+    wms->surface.winsys = ws;
+
+    return &wms->surface;
+}
+
+static void
+exa_surface_release(struct pipe_winsys *winsys, struct pipe_surface **s)
+{
+    struct pipe_surface *surf = *s;
+
+    surf->refcount--;
+    if (surf->refcount == 0) {
+	if (surf->buffer)
+	    pipe_buffer_reference(winsys, &surf->buffer, NULL);
+	free(surf);
+    }
+    *s = NULL;
+}
+
+/*
+ * Fence functions - basically nothing to do, as we don't create any actual
+ * fence objects.
+ */
+static void
+exa_fence_reference(struct pipe_winsys *sws, struct pipe_fence_handle **ptr,
+		    struct pipe_fence_handle *fence)
+{
+}
+
+static int
+exa_fence_signalled(struct pipe_winsys *sws, struct pipe_fence_handle *fence,
+		    unsigned flag)
+{
+    return 0;
+}
+
+static int
+exa_fence_finish(struct pipe_winsys *sws, struct pipe_fence_handle *fence,
+		 unsigned flag)
+{
+    return 0;
+}
+
+struct pipe_winsys *
+exa_get_pipe_winsys(modesettingPtr ms)
+{
+    static struct exa_winsys *ws = NULL;
+
+    if (!ws) {
+	ws = xcalloc(1, sizeof(struct exa_winsys));
+
+	/* Fill in this struct with callbacks that pipe will need to
+	 * communicate with the window system, buffer manager, etc.
+	 */
+	ws->base.buffer_create = exa_buffer_create;
+	ws->base.user_buffer_create = exa_user_buffer_create;
+	ws->base.buffer_map = exa_buffer_map;
+	ws->base.buffer_unmap = exa_buffer_unmap;
+	ws->base.buffer_destroy = exa_buffer_destroy;
+
+	ws->base.surface_alloc = exa_surface_alloc;
+	ws->base.surface_alloc_storage = exa_surface_alloc_storage;
+	ws->base.surface_release = exa_surface_release;
+
+	ws->base.fence_reference = exa_fence_reference;
+	ws->base.fence_signalled = exa_fence_signalled;
+	ws->base.fence_finish = exa_fence_finish;
+
+	ws->base.flush_frontbuffer = exa_flush_frontbuffer;
+	ws->base.get_name = exa_get_name;
+
+	ws->ms = ms;
+    }
+
+    return &ws->base;
+}
+
+/* EXA functions */
+
+struct PixmapPriv
+{
+    drmBO bo;
+#if 0
+    dri_fence *fence;
+#endif
+    int flags;
+
+    struct pipe_texture *tex;
+    unsigned int color;
+    struct pipe_surface *src_surf;     /* for copies */
+};
+
+static enum pipe_format
+exa_get_pipe_format(int depth)
+{
+    switch (depth) {
+    case 32:
+    case 24:
+	return PIPE_FORMAT_A8R8G8B8_UNORM;
+    case 16:
+	return PIPE_FORMAT_R5G6B5_UNORM;
+    case 15:
+	return PIPE_FORMAT_A1R5G5B5_UNORM;
+    case 8:
+    case 4:
+    case 1:
+	return PIPE_FORMAT_A8R8G8B8_UNORM;	/* bad bad bad */
+    default:
+	assert(0);
+	return 0;
+    }
+}
+
+/*
+ * EXA functions
+ */
+
+static void
+ExaWaitMarker(ScreenPtr pScreen, int marker)
+{
+}
+
+static int
+ExaMarkSync(ScreenPtr pScreen)
+{
+    return 1;
+}
+
+Bool
+ExaPrepareAccess(PixmapPtr pPix, int index)
+{
+    ScreenPtr pScreen = pPix->drawable.pScreen;
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    modesettingPtr ms = modesettingPTR(pScrn);
+    PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);
+    struct exa_entity *exa = ms->exa;
+    struct PixmapPriv *priv;
+    int ret;
+
+    priv = exaGetPixmapDriverPrivate(pPix);
+
+    if (!priv)
+	return FALSE;
+
+    if (!priv->tex)
+	return FALSE;
+    {
+	struct pipe_surface *surf =
+	    exa->scrn->get_tex_surface(exa->scrn, priv->tex, 0, 0, 0,
+				       PIPE_BUFFER_USAGE_CPU_READ |
+				       PIPE_BUFFER_USAGE_CPU_WRITE);
+	pPix->devPrivate.ptr =
+	    exa->scrn->surface_map(exa->scrn, surf,
+				   PIPE_BUFFER_USAGE_CPU_READ |
+				   PIPE_BUFFER_USAGE_CPU_WRITE);
+	exa->scrn->tex_surface_release(exa->scrn, &surf);
+    }
+
+    return TRUE;
+}
+
+void
+ExaFinishAccess(PixmapPtr pPix, int index)
+{
+    ScreenPtr pScreen = pPix->drawable.pScreen;
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    modesettingPtr ms = modesettingPTR(pScrn);
+    PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);
+    struct PixmapPriv *priv;
+    struct exa_entity *exa = ms->exa;
+    int ret;
+
+    priv = exaGetPixmapDriverPrivate(pPix);
+
+    if (!priv)
+	return;
+
+    if (!priv->tex)
+	return;
+    {
+	struct pipe_surface *surf =
+	    exa->scrn->get_tex_surface(exa->scrn, priv->tex, 0, 0, 0,
+				       PIPE_BUFFER_USAGE_CPU_READ |
+				       PIPE_BUFFER_USAGE_CPU_WRITE);
+	exa->scrn->surface_unmap(exa->scrn, surf);
+	exa->scrn->tex_surface_release(exa->scrn, &surf);
+	pPix->devPrivate.ptr = NULL;
+    }
+}
+
+static void
+ExaDone(PixmapPtr pPixmap)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
+    modesettingPtr ms = modesettingPTR(pScrn);
+    struct PixmapPriv *priv = exaGetPixmapDriverPrivate(pPixmap);
+    struct exa_entity *exa = ms->exa;
+
+    if (!priv)
+	return;
+
+    if (priv->src_surf)
+	exa->scrn->tex_surface_release(exa->scrn, &priv->src_surf);
+    priv->src_surf = NULL;
+}
+
+static void
+ExaDoneComposite(PixmapPtr pPixmap)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
+}
+
+static Bool
+ExaPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planeMask, Pixel fg)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
+    modesettingPtr ms = modesettingPTR(pScrn);
+    struct PixmapPriv *priv = exaGetPixmapDriverPrivate(pPixmap);
+    struct exa_entity *exa = ms->exa;
+
+    if (pPixmap->drawable.depth < 15)
+	return FALSE;
+
+    if (!EXA_PM_IS_SOLID(&pPixmap->drawable, planeMask))
+	return FALSE;
+
+    if (!priv || !priv->tex)
+	return FALSE;
+
+    if (alu != GXcopy)
+	return FALSE;
+
+    if (!exa->ctx || !exa->ctx->surface_fill)
+	return FALSE;
+
+    priv->color = fg;
+
+    return TRUE;
+}
+
+static void
+ExaSolid(PixmapPtr pPixmap, int x0, int y0, int x1, int y1)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
+    modesettingPtr ms = modesettingPTR(pScrn);
+    struct exa_entity *exa = ms->exa;
+    struct PixmapPriv *priv = exaGetPixmapDriverPrivate(pPixmap);
+    struct pipe_surface *surf =
+	exa->scrn->get_tex_surface(exa->scrn, priv->tex, 0, 0, 0,
+				   PIPE_BUFFER_USAGE_GPU_READ |
+				   PIPE_BUFFER_USAGE_GPU_WRITE);
+
+    exa->ctx->surface_fill(exa->ctx, surf, x0, y0, x1 - x0, y1 - y0,
+			   priv->color);
+
+    exa->scrn->tex_surface_release(exa->scrn, &surf);
+}
+
+static Bool
+ExaPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir,
+	       int ydir, int alu, Pixel planeMask)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
+    modesettingPtr ms = modesettingPTR(pScrn);
+    struct exa_entity *exa = ms->exa;
+    struct pipe_surface *src_surf;
+    struct PixmapPriv *priv = exaGetPixmapDriverPrivate(pDstPixmap);
+    struct PixmapPriv *src_priv = exaGetPixmapDriverPrivate(pSrcPixmap);
+
+    if (alu != GXcopy)
+	return FALSE;
+
+    if (pSrcPixmap->drawable.depth < 15 || pDstPixmap->drawable.depth < 15)
+	return FALSE;
+
+    if (!EXA_PM_IS_SOLID(&pSrcPixmap->drawable, planeMask))
+	return FALSE;
+
+    if (!priv || !src_priv)
+	return FALSE;
+
+    if (!priv->tex || !src_priv->tex)
+	return FALSE;
+
+    if (!exa->ctx || !exa->ctx->surface_copy)
+	return FALSE;
+
+    priv->src_surf =
+	exa->scrn->get_tex_surface(exa->scrn, src_priv->tex, 0, 0, 0,
+				   PIPE_BUFFER_USAGE_GPU_READ |
+				   PIPE_BUFFER_USAGE_GPU_WRITE);
+
+    return FALSE;
+}
+
+static void
+ExaCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY,
+	int width, int height)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
+    modesettingPtr ms = modesettingPTR(pScrn);
+    struct exa_entity *exa = ms->exa;
+    struct PixmapPriv *priv = exaGetPixmapDriverPrivate(pDstPixmap);
+    struct pipe_surface *surf =
+	exa->scrn->get_tex_surface(exa->scrn, priv->tex, 0, 0, 0,
+				   PIPE_BUFFER_USAGE_GPU_READ |
+				   PIPE_BUFFER_USAGE_GPU_WRITE);
+
+    exa->ctx->surface_copy(exa->ctx, 0, surf, dstX, dstY, priv->src_surf,
+			   srcX, srcY, width, height);
+    exa->scrn->tex_surface_release(exa->scrn, &surf);
+}
+
+static Bool
+ExaPrepareComposite(int op, PicturePtr pSrcPicture,
+		    PicturePtr pMaskPicture, PicturePtr pDstPicture,
+		    PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
+{
+    ScreenPtr pScreen = pDst->drawable.pScreen;
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+
+    return FALSE;
+}
+
+static Bool
+ExaUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, char *src,
+		  int src_pitch)
+{
+    ScreenPtr pScreen = pDst->drawable.pScreen;
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+
+    ErrorF("UPLOAD\n");
+
+    return FALSE;
+}
+
+static void
+ExaComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
+	     int dstX, int dstY, int width, int height)
+{
+    ScreenPtr pScreen = pDst->drawable.pScreen;
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+}
+
+static Bool
+ExaCheckComposite(int op,
+		  PicturePtr pSrcPicture, PicturePtr pMaskPicture,
+		  PicturePtr pDstPicture)
+{
+    DrawablePtr pDraw = pSrcPicture->pDrawable;
+    int w = pDraw->width;
+    int h = pDraw->height;
+
+    return FALSE;
+}
+
+static void *
+ExaCreatePixmap(ScreenPtr pScreen, int size, int align)
+{
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    modesettingPtr ms = modesettingPTR(pScrn);
+    struct PixmapPriv *priv;
+    void *virtual;
+
+    priv = xcalloc(1, sizeof(struct PixmapPriv));
+    if (!priv)
+	return NULL;
+
+    return priv;
+}
+
+static void
+ExaDestroyPixmap(ScreenPtr pScreen, void *dPriv)
+{
+    struct PixmapPriv *priv = (struct PixmapPriv *)dPriv;
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    modesettingPtr ms = modesettingPTR(pScrn);
+    struct exa_entity *exa = ms->exa;
+
+    if (!priv)
+	return;
+
+    if (priv->tex)
+	exa->scrn->texture_release(exa->scrn, &priv->tex);
+
+    xfree(priv);
+}
+
+static Bool
+ExaPixmapIsOffscreen(PixmapPtr pPixmap)
+{
+    struct PixmapPriv *priv;
+    ScreenPtr pScreen = pPixmap->drawable.pScreen;
+    PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);
+
+    priv = exaGetPixmapDriverPrivate(pPixmap);
+
+    if (!priv)
+	return FALSE;
+
+    if (priv->tex)
+	return TRUE;
+
+    return FALSE;
+}
+
+/* FIXME !! */
+unsigned int
+driGetPixmapHandle(PixmapPtr pPixmap, unsigned int *flags)
+{
+    ScreenPtr pScreen = pPixmap->drawable.pScreen;
+    PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    modesettingPtr ms = modesettingPTR(pScrn);
+    struct exa_entity *exa = ms->exa;
+    struct exa_buffer *exa_buf;
+    struct pipe_surface *surf;
+    struct PixmapPriv *priv;
+
+    *flags = 0;
+
+    if (!ms->exa) {
+	FatalError("NO MS->EXA\n");
+	return 0;
+    }
+
+    priv = exaGetPixmapDriverPrivate(pPixmap);
+
+    if (!priv) {
+	FatalError("NO PIXMAP PRIVATE\n");
+	return 0;
+    }
+
+    surf =
+	exa->scrn->get_tex_surface(exa->scrn, priv->tex, 0, 0, 0,
+				   PIPE_BUFFER_USAGE_CPU_READ |
+				   PIPE_BUFFER_USAGE_CPU_WRITE);
+    exa_buf = exa_get_buffer(surf->buffer);
+    exa->scrn->tex_surface_release(exa->scrn, &surf);
+
+    if (exa_buf->bo.handle)
+	return exa_buf->bo.handle;
+
+    return 0;
+}
+
+static Bool
+ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
+		      int depth, int bitsPerPixel, int devKind,
+		      pointer pPixData)
+{
+    ScreenPtr pScreen = pPixmap->drawable.pScreen;
+    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+    struct PixmapPriv *priv = exaGetPixmapDriverPrivate(pPixmap);
+    modesettingPtr ms = modesettingPTR(pScrn);
+    PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);
+    struct exa_entity *exa = ms->exa;
+
+    if (!priv)
+	return FALSE;
+
+    if (depth <= 0)
+	depth = pPixmap->drawable.depth;
+
+    if (bitsPerPixel <= 0)
+	bitsPerPixel = pPixmap->drawable.bitsPerPixel;
+
+    if (width <= 0)
+	width = pPixmap->drawable.width;
+
+    if (height <= 0)
+	height = pPixmap->drawable.height;
+
+    if (width <= 0 || height <= 0 || depth <= 0)
+	return FALSE;
+
+    miModifyPixmapHeader(pPixmap, width, height, depth,
+			     bitsPerPixel, devKind, NULL);
+
+    /* Deal with screen resize */
+    if (priv->tex) {
+	struct pipe_surface *surf =
+	    exa->scrn->get_tex_surface(exa->scrn, priv->tex, 0, 0, 0,
+				       PIPE_BUFFER_USAGE_CPU_READ |
+				       PIPE_BUFFER_USAGE_CPU_WRITE);
+
+	ErrorF("RESIZE %d %d to %d %d\n", surf->width, surf->height, width,
+	       height);
+	if (surf->width != width || surf->height != height) {
+	    exa->scrn->texture_release(exa->scrn, &priv->tex);
+	    priv->tex = NULL;
+	}
+	exa->scrn->tex_surface_release(exa->scrn, &surf);
+    }
+
+    if (!priv->tex) {
+	struct pipe_texture template;
+
+	memset(&template, 0, sizeof(template));
+	template.target = PIPE_TEXTURE_2D;
+	template.compressed = 0;
+	template.format = exa_get_pipe_format(depth);
+	pf_get_block(template.format, &template.block);
+	template.width[0] = width;
+	template.height[0] = height;
+	template.depth[0] = 1;
+	template.last_level = 0;
+	template.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET;
+	priv->tex = exa->scrn->texture_create(exa->scrn, &template);
+    }
+
+    return TRUE;
+}
+
+void
+ExaClose(ScrnInfoPtr pScrn)
+{
+    modesettingPtr ms = modesettingPTR(pScrn);
+    struct exa_entity *exa = ms->exa;
+
+    exaDriverFini(pScrn->pScreen);
+
+    dlclose(ms->driver);
+}
+
+void *GlamoKMSExaInit(ScrnInfoPtr pScrn)
+{
+    modesettingPtr ms = modesettingPTR(pScrn);
+    struct exa_entity *exa;
+    ExaDriverPtr pExa;
+
+    exa = xcalloc(1, sizeof(struct exa_entity));
+    if (!exa)
+	return NULL;
+
+    pExa = exaDriverAlloc();
+    if (!pExa) {
+	goto out_err;
+    }
+
+    memset(pExa, 0, sizeof(*pExa));
+    pExa->exa_major = 2;
+    pExa->exa_minor = 4;
+    pExa->memoryBase = 0;
+    pExa->memorySize = 0;
+    pExa->offScreenBase = 0;
+    pExa->pixmapOffsetAlign = 0;
+    pExa->pixmapPitchAlign = 1;
+    pExa->flags = EXA_OFFSCREEN_PIXMAPS | EXA_HANDLES_PIXMAPS;
+    pExa->maxX = 8191;		       /* FIXME */
+    pExa->maxY = 8191;		       /* FIXME */
+    pExa->WaitMarker = ExaWaitMarker;
+    pExa->MarkSync = ExaMarkSync;
+    pExa->PrepareSolid = ExaPrepareSolid;
+    pExa->Solid = ExaSolid;
+    pExa->DoneSolid = ExaDone;
+    pExa->PrepareCopy = ExaPrepareCopy;
+    pExa->Copy = ExaCopy;
+    pExa->DoneCopy = ExaDone;
+    pExa->CheckComposite = ExaCheckComposite;
+    pExa->PrepareComposite = ExaPrepareComposite;
+    pExa->Composite = ExaComposite;
+    pExa->DoneComposite = ExaDoneComposite;
+    pExa->PixmapIsOffscreen = ExaPixmapIsOffscreen;
+    pExa->PrepareAccess = ExaPrepareAccess;
+    pExa->FinishAccess = ExaFinishAccess;
+    pExa->UploadToScreen = ExaUploadToScreen;
+    pExa->CreatePixmap = ExaCreatePixmap;
+    pExa->DestroyPixmap = ExaDestroyPixmap;
+    pExa->ModifyPixmapHeader = ExaModifyPixmapHeader;
+
+    if (!exaDriverInit(pScrn->pScreen, pExa)) {
+	goto out_err;
+    }
+
+    {
+	char filename[128];
+	char dri_driver_path[] = DRI_DRIVER_PATH;
+
+	snprintf(filename, sizeof filename,
+		 "%s/%s_dri.so", dri_driver_path, "i915");
+
+	ms->driver = dlopen(filename, RTLD_NOW | RTLD_DEEPBIND | RTLD_GLOBAL);
+	if (!ms->driver)
+		FatalError("failed to initialize i915 - for softpipe only.\n");
+
+	exa->c = xcalloc(1, sizeof(struct exa_context));
+
+	exa->ws = exa_get_pipe_winsys(ms);
+	if (!exa->ws)
+		FatalError("BAD WINSYS\n");
+
+	exa->scrn = softpipe_create_screen(exa->ws);
+	if (!exa->scrn)
+		FatalError("BAD SCREEN\n");
+
+	exa->ctx = softpipe_create(exa->scrn, exa->ws, NULL);
+	if (!exa->ctx)
+	   	FatalError("BAD CTX\n");
+
+	exa->ctx->priv = exa->c;
+    }
+
+    return (void *)exa;
+
+  out_err:
+    ExaClose(pScrn);
+
+    return NULL;
+}
diff --git a/src/glamo-kms-exa.h b/src/glamo-kms-exa.h
new file mode 100644
index 0000000..6649892
--- /dev/null
+++ b/src/glamo-kms-exa.h
@@ -0,0 +1,25 @@
+/*
+ * EXA via DRI for the SMedia Glamo3362 X.org Driver
+ *
+ * Copyright 2009 Thomas White <taw at bitwiz.org.uk>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#include "xf86.h"
+
+extern void *GlamoKMSExaInit(ScrnInfoPtr pScrn);

-- 
xf86-video-glamo, SMedia Glamo video driver for X.Org



More information about the pkg-fso-commits mailing list