summaryrefslogtreecommitdiff
path: root/hw/xfree86/dri2
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@redhat.com>2008-03-26 19:28:09 -0400
committerKristian Høgsberg <krh@redhat.com>2008-03-31 16:50:58 -0400
commitc40e0b51f0d9ef5e1f30f233d7db1e6db9d6681b (patch)
tree42c40d8123a53c2f04ef0df3144f112395ad75cb /hw/xfree86/dri2
parent8074676d2df8d577b443e3fa5e22d7c71c944bd1 (diff)
Implement DRI2 direct rendering and update AIGLX to DRI interface changes.
Get rid of glcontextmodes.[ch] from build, rename __GlcontextModes to __GLXcontext. Drop all #includes of glcontextmodes.h and glcore.h. Drop the DRI context modes extension. Add protocol code to DRI2 module and load DRI2 extension by default.
Diffstat (limited to 'hw/xfree86/dri2')
-rw-r--r--hw/xfree86/dri2/Makefile.am5
-rw-r--r--hw/xfree86/dri2/dri2.c107
-rw-r--r--hw/xfree86/dri2/dri2.h16
-rw-r--r--hw/xfree86/dri2/dri2ext.c361
4 files changed, 444 insertions, 45 deletions
diff --git a/hw/xfree86/dri2/Makefile.am b/hw/xfree86/dri2/Makefile.am
index be3cea48f..844c91240 100644
--- a/hw/xfree86/dri2/Makefile.am
+++ b/hw/xfree86/dri2/Makefile.am
@@ -2,7 +2,7 @@ libdri2_la_LTLIBRARIES = libdri2.la
libdri2_la_CFLAGS = \
-DHAVE_XORG_CONFIG_H \
-I@MESA_SOURCE@/include \
- @DIX_CFLAGS@ @DRIPROTO_CFLAGS@ @LIBDRM_CFLAGS@ \
+ @DIX_CFLAGS@ @DRI2PROTO_CFLAGS@ @LIBDRM_CFLAGS@ \
-I$(top_srcdir)/hw/xfree86/common \
-I$(top_srcdir)/hw/xfree86/os-support/bus
@@ -10,6 +10,7 @@ libdri2_la_LDFLAGS = -module -avoid-version @LIBDRM_LIBS@
libdri2_ladir = $(moduledir)/extensions
libdri2_la_SOURCES = \
dri2.c \
- dri2.h
+ dri2.h \
+ dri2ext.c
sdk_HEADERS = dri2.h
diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
index d5273877e..74aef7196 100644
--- a/hw/xfree86/dri2/dri2.c
+++ b/hw/xfree86/dri2/dri2.c
@@ -38,6 +38,8 @@
#include "xf86Module.h"
#include "scrnintstr.h"
#include "windowstr.h"
+#include "region.h"
+#include "damage.h"
#include "dri2.h"
#include <GL/internal/dri_sarea.h>
@@ -48,8 +50,9 @@ static DevPrivateKey dri2WindowPrivateKey = &dri2WindowPrivateKey;
static DevPrivateKey dri2PixmapPrivateKey = &dri2PixmapPrivateKey;
typedef struct _DRI2DrawablePriv {
- drm_drawable_t drawable;
- unsigned int handle;
+ unsigned int refCount;
+ unsigned int boHandle;
+ unsigned int dri2Handle;
} DRI2DrawablePrivRec, *DRI2DrawablePrivPtr;
typedef struct _DRI2Screen {
@@ -58,6 +61,7 @@ typedef struct _DRI2Screen {
void *sarea;
unsigned int sareaSize;
const char *driverName;
+ unsigned int nextHandle;
__DRIEventBuffer *buffer;
int locked;
@@ -147,7 +151,7 @@ DRI2PostDrawableConfig(DrawablePtr pDraw)
e = DRI2ScreenAllocEvent(ds, size);
e->event_header = DRI2_EVENT_HEADER(DRI2_EVENT_DRAWABLE_CONFIG, size);
- e->drawable = pPriv->drawable;
+ e->drawable = pPriv->dri2Handle;
e->x = pDraw->x - pPixmap->screen_x;
e->y = pDraw->y - pPixmap->screen_y;
e->width = pDraw->width;
@@ -164,7 +168,7 @@ DRI2PostDrawableConfig(DrawablePtr pDraw)
}
static void
-DRI2PostBufferAttach(DrawablePtr pDraw)
+DRI2PostBufferAttach(DrawablePtr pDraw, Bool force)
{
ScreenPtr pScreen = pDraw->pScreen;
DRI2ScreenPtr ds = DRI2GetScreen(pScreen);
@@ -173,7 +177,8 @@ DRI2PostBufferAttach(DrawablePtr pDraw)
PixmapPtr pPixmap;
__DRIBufferAttachEvent *e;
size_t size;
- unsigned int handle, flags;
+ unsigned int flags;
+ unsigned int boHandle;
if (pDraw->type == DRAWABLE_WINDOW) {
pWin = (WindowPtr) pDraw;
@@ -187,22 +192,20 @@ DRI2PostBufferAttach(DrawablePtr pDraw)
if (!pPriv)
return;
- size = sizeof *e;
-
- handle = ds->getPixmapHandle(pPixmap, &flags);
- if (handle == 0 || handle == pPriv->handle)
+ boHandle = ds->getPixmapHandle(pPixmap, &flags);
+ if (boHandle == pPriv->boHandle && !force)
return;
+ pPriv->boHandle = boHandle;
+ size = sizeof *e;
e = DRI2ScreenAllocEvent(ds, size);
e->event_header = DRI2_EVENT_HEADER(DRI2_EVENT_BUFFER_ATTACH, size);
- e->drawable = pPriv->drawable;
+ e->drawable = pPriv->dri2Handle;
e->buffer.attachment = DRI_DRAWABLE_BUFFER_FRONT_LEFT;
- e->buffer.handle = handle;
+ e->buffer.handle = pPriv->boHandle;
e->buffer.pitch = pPixmap->devKind;
e->buffer.cpp = pPixmap->drawable.bitsPerPixel / 8;
e->buffer.flags = flags;
-
- pPriv->handle = handle;
}
static void
@@ -223,7 +226,7 @@ DRI2ClipNotify(WindowPtr pWin, int dx, int dy)
}
DRI2PostDrawableConfig(&pWin->drawable);
- DRI2PostBufferAttach(&pWin->drawable);
+ DRI2PostBufferAttach(&pWin->drawable, FALSE);
}
static void
@@ -262,10 +265,10 @@ DRI2CloseScreen(ScreenPtr pScreen)
}
Bool
-DRI2CreateDrawable(ScreenPtr pScreen, DrawablePtr pDraw,
- drm_drawable_t *pDrmDrawable, unsigned int *head)
+DRI2CreateDrawable(DrawablePtr pDraw,
+ unsigned int *handle, unsigned int *head)
{
- DRI2ScreenPtr ds = DRI2GetScreen(pScreen);
+ DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
WindowPtr pWin;
PixmapPtr pPixmap;
DRI2DrawablePrivPtr pPriv;
@@ -283,47 +286,66 @@ DRI2CreateDrawable(ScreenPtr pScreen, DrawablePtr pDraw,
}
pPriv = dixLookupPrivate(devPrivates, key);
- if (pPriv == NULL) {
+ if (pPriv != NULL) {
+ pPriv->refCount++;
+ } else {
pPriv = xalloc(sizeof *pPriv);
- if (drmCreateDrawable(ds->fd, &pPriv->drawable))
- return FALSE;
-
+ pPriv->refCount = 1;
+ pPriv->boHandle = 0;
+ pPriv->dri2Handle = ds->nextHandle++;
dixSetPrivate(devPrivates, key, pPriv);
}
- *pDrmDrawable = pPriv->drawable;
-
+ *handle = pPriv->dri2Handle;
*head = ds->buffer->head;
+
DRI2PostDrawableConfig(pDraw);
- DRI2PostBufferAttach(pDraw);
+ DRI2PostBufferAttach(pDraw, TRUE);
DRI2ScreenCommitEvents(ds);
return TRUE;
}
void
-DRI2DestroyDrawable(ScreenPtr pScreen, DrawablePtr pDraw)
+DRI2DestroyDrawable(DrawablePtr pDraw)
{
- DRI2ScreenPtr ds = DRI2GetScreen(pScreen);
- PixmapPtr pPixmap;
- WindowPtr pWin;
- DRI2DrawablePrivPtr pPriv;
+ PixmapPtr pPixmap;
+ WindowPtr pWin;
+ DRI2DrawablePrivPtr pPriv;
+ DevPrivateKey key;
+ PrivateRec **devPrivates;
if (pDraw->type == DRAWABLE_WINDOW) {
pWin = (WindowPtr) pDraw;
- pPriv = dixLookupPrivate(&pWin->devPrivates, dri2WindowPrivateKey);
- dixSetPrivate(&pWin->devPrivates, dri2WindowPrivateKey, NULL);
+ devPrivates = &pWin->devPrivates;
+ key = dri2WindowPrivateKey;
} else {
pPixmap = (PixmapPtr) pDraw;
- pPriv = dixLookupPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey);
- dixSetPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey, NULL);
+ devPrivates = &pPixmap->devPrivates;
+ key = dri2PixmapPrivateKey;
}
+ pPriv = dixLookupPrivate(devPrivates, key);
if (pPriv == NULL)
return;
- drmDestroyDrawable(ds->fd, pPriv->drawable);
- xfree(pPriv);
+ pPriv->refCount--;
+ if (pPriv->refCount == 0) {
+ dixSetPrivate(devPrivates, key, NULL);
+ xfree(pPriv);
+ }
+}
+
+void
+DRI2ReemitDrawableInfo(DrawablePtr pDraw, unsigned int *head)
+{
+ DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
+
+ *head = ds->buffer->head;
+
+ DRI2PostDrawableConfig(pDraw);
+ DRI2PostBufferAttach(pDraw, TRUE);
+ DRI2ScreenCommitEvents(ds);
}
Bool
@@ -409,8 +431,9 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
if (!ds)
return NULL;
- ds->fd = info->fd;
+ ds->fd = info->fd;
ds->driverName = info->driverName;
+ ds->nextHandle = 1;
ds->getPixmapHandle = info->getPixmapHandle;
ds->beginClipNotify = info->beginClipNotify;
@@ -434,9 +457,21 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
return p;
}
+extern ExtensionModule dri2ExtensionModule;
+
static pointer
DRI2Setup(pointer module, pointer opts, int *errmaj, int *errmin)
{
+ static Bool setupDone = FALSE;
+
+ if (!setupDone) {
+ setupDone = TRUE;
+ LoadExtension(&dri2ExtensionModule, FALSE);
+ } else {
+ if (errmaj)
+ *errmaj = LDR_ONCEONLY;
+ }
+
return (pointer) 1;
}
diff --git a/hw/xfree86/dri2/dri2.h b/hw/xfree86/dri2/dri2.h
index 126087a2f..85b3da41c 100644
--- a/hw/xfree86/dri2/dri2.h
+++ b/hw/xfree86/dri2/dri2.h
@@ -66,14 +66,16 @@ unsigned int DRI2GetPixmapHandle(PixmapPtr pPixmap,
void DRI2Lock(ScreenPtr pScreen);
void DRI2Unlock(ScreenPtr pScreen);
-Bool DRI2CreateDrawable(ScreenPtr pScreen,
- DrawablePtr pDraw,
- drm_drawable_t *pDrmDrawable,
- unsigned int *head);
+Bool DRI2CreateDrawable(DrawablePtr pDraw,
+ unsigned int *handle,
+ unsigned int *head);
-void DRI2DestroyDrawable(ScreenPtr pScreen,
- DrawablePtr pDraw);
+void DRI2DestroyDrawable(DrawablePtr pDraw);
-void DRI2ExtensionInit(void);
+void DRI2ReemitDrawableInfo(DrawablePtr pDraw,
+ unsigned int *head);
+
+Bool DRI2PostDamage(DrawablePtr pDrawable,
+ struct drm_clip_rect *rects, int numRects);
#endif
diff --git a/hw/xfree86/dri2/dri2ext.c b/hw/xfree86/dri2/dri2ext.c
new file mode 100644
index 000000000..ca2e02970
--- /dev/null
+++ b/hw/xfree86/dri2/dri2ext.c
@@ -0,0 +1,361 @@
+/*
+ * Copyright © 2008 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Soft-
+ * ware"), to deal in the Software without restriction, including without
+ * limitation the rights to use, copy, modify, merge, publish, distribute,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, provided that the above copyright
+ * notice(s) and this permission notice appear in all copies of the Soft-
+ * ware and that both the above copyright notice(s) and this permission
+ * notice appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+ * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
+ * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
+ * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
+ * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
+ * MANCE OF THIS SOFTWARE.
+ *
+ * Except as contained in this notice, the name of a copyright holder shall
+ * not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization of
+ * the copyright holder.
+ *
+ * Authors:
+ * Kristian Høgsberg (krh@redhat.com)
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#define NEED_REPLIES
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include "dixstruct.h"
+#include "scrnintstr.h"
+#include "pixmapstr.h"
+#include "extnsionst.h"
+#include "xf86drm.h"
+#include "dri2proto.h"
+#include "dri2.h"
+
+/* The only xf86 include */
+#include "xf86Module.h"
+
+static ExtensionEntry *dri2Extension;
+static RESTYPE dri2DrawableRes;
+
+static Bool
+validScreen(ClientPtr client, int screen, ScreenPtr *pScreen)
+{
+ if (screen >= screenInfo.numScreens) {
+ client->errorValue = screen;
+ return FALSE;
+ }
+
+ *pScreen = screenInfo.screens[screen];
+
+ return TRUE;
+}
+
+static Bool
+validDrawable(ClientPtr client, XID drawable,
+ DrawablePtr *pDrawable, int *status)
+{
+ *status = dixLookupDrawable(pDrawable, drawable, client, 0, DixReadAccess);
+ if (*status != Success) {
+ client->errorValue = drawable;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static int
+ProcDRI2QueryVersion(ClientPtr client)
+{
+ REQUEST(xDRI2QueryVersionReq);
+ xDRI2QueryVersionReply rep;
+ int n;
+
+ if (client->swapped)
+ swaps(&stuff->length, n);
+
+ REQUEST_SIZE_MATCH(xDRI2QueryVersionReq);
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.majorVersion = DRI2_MAJOR;
+ rep.minorVersion = DRI2_MINOR;
+
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ swapl(&rep.majorVersion, n);
+ swapl(&rep.minorVersion, n);
+ }
+
+ WriteToClient(client, sizeof(xDRI2QueryVersionReply), &rep);
+
+ return client->noClientException;
+}
+
+static int
+ProcDRI2Connect(ClientPtr client)
+{
+ REQUEST(xDRI2ConnectReq);
+ xDRI2ConnectReply rep;
+ ScreenPtr pScreen;
+ int fd;
+ const char *driverName;
+ char *busId;
+ unsigned int sareaHandle;
+
+ REQUEST_SIZE_MATCH(xDRI2ConnectReq);
+ if (!validScreen(client, stuff->screen, &pScreen))
+ return BadValue;
+
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.driverNameLength = 0;
+ rep.busIdLength = 0;
+ rep.sareaHandle = 0;
+
+ if (!DRI2Connect(pScreen, &fd, &driverName, &sareaHandle))
+ goto fail;
+
+ busId = drmGetBusid(fd);
+ if (busId == NULL)
+ goto fail;
+
+ rep.driverNameLength = strlen(driverName);
+ rep.busIdLength = strlen(busId);
+ rep.sareaHandle = sareaHandle;
+ rep.length = (rep.driverNameLength + 3) / 4 + (rep.busIdLength + 3) / 4;
+
+ fail:
+ WriteToClient(client, sizeof(xDRI2ConnectReply), &rep);
+ WriteToClient(client, rep.driverNameLength, driverName);
+ WriteToClient(client, rep.busIdLength, busId);
+ drmFreeBusid(busId);
+
+ return client->noClientException;
+}
+
+static int
+ProcDRI2AuthConnection(ClientPtr client)
+{
+ REQUEST(xDRI2AuthConnectionReq);
+ xDRI2AuthConnectionReply rep;
+ ScreenPtr pScreen;
+
+ REQUEST_SIZE_MATCH(xDRI2AuthConnectionReq);
+ if (!validScreen(client, stuff->screen, &pScreen))
+ return BadValue;
+
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.authenticated = 1;
+
+ if (!DRI2AuthConnection(pScreen, stuff->magic)) {
+ ErrorF("DRI2: Failed to authenticate %lu\n",
+ (unsigned long) stuff->magic);
+ rep.authenticated = 0;
+ }
+
+ WriteToClient(client, sizeof(xDRI2AuthConnectionReply), &rep);
+
+ return client->noClientException;
+}
+
+static int
+ProcDRI2CreateDrawable(ClientPtr client)
+{
+ REQUEST(xDRI2CreateDrawableReq);
+ xDRI2CreateDrawableReply rep;
+ DrawablePtr pDrawable;
+ unsigned int handle, head;
+ int status;
+
+ REQUEST_SIZE_MATCH(xDRI2CreateDrawableReq);
+
+ if (!validDrawable(client, stuff->drawable, &pDrawable, &status))
+ return status;
+
+ if (!DRI2CreateDrawable(pDrawable, &handle, &head))
+ return BadMatch;
+
+ if (!AddResource(stuff->drawable, dri2DrawableRes, pDrawable)) {
+ DRI2DestroyDrawable(pDrawable);
+ return BadAlloc;
+ }
+
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.handle = handle;
+ rep.head = head;
+
+ WriteToClient(client, sizeof(xDRI2CreateDrawableReply), &rep);
+
+ return client->noClientException;
+}
+
+static int
+ProcDRI2DestroyDrawable(ClientPtr client)
+{
+ REQUEST(xDRI2DestroyDrawableReq);
+ DrawablePtr pDrawable;
+ int status;
+
+ REQUEST_SIZE_MATCH(xDRI2DestroyDrawableReq);
+ if (!validDrawable(client, stuff->drawable, &pDrawable, &status))
+ return status;
+
+ FreeResourceByType(stuff->drawable, dri2DrawableRes, FALSE);
+
+ return client->noClientException;
+}
+
+static int
+ProcDRI2ReemitDrawableInfo(ClientPtr client)
+{
+ REQUEST(xDRI2ReemitDrawableInfoReq);
+ xDRI2ReemitDrawableInfoReply rep;
+ DrawablePtr pDrawable;
+ unsigned int head;
+ int status;
+
+ REQUEST_SIZE_MATCH(xDRI2ReemitDrawableInfoReq);
+ if (!validDrawable(client, stuff->drawable, &pDrawable, &status))
+ return status;
+
+ DRI2ReemitDrawableInfo(pDrawable, &head);
+
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.head = head;
+
+ WriteToClient(client, sizeof(xDRI2ReemitDrawableInfoReply), &rep);
+
+ return client->noClientException;
+}
+
+static int
+ProcDRI2Dispatch (ClientPtr client)
+{
+ REQUEST(xReq);
+
+ switch (stuff->data) {
+ case X_DRI2QueryVersion:
+ return ProcDRI2QueryVersion(client);
+ }
+
+ if (!LocalClient(client))
+ return BadRequest;
+
+ switch (stuff->data) {
+ case X_DRI2Connect:
+ return ProcDRI2Connect(client);
+ case X_DRI2AuthConnection:
+ return ProcDRI2AuthConnection(client);
+ case X_DRI2CreateDrawable:
+ return ProcDRI2CreateDrawable(client);
+ case X_DRI2DestroyDrawable:
+ return ProcDRI2DestroyDrawable(client);
+ case X_DRI2ReemitDrawableInfo:
+ return ProcDRI2ReemitDrawableInfo(client);
+ default:
+ return BadRequest;
+ }
+}
+
+static int
+SProcDRI2Connect(ClientPtr client)
+{
+ REQUEST(xDRI2ConnectReq);
+ xDRI2ConnectReply rep;
+ int n;
+
+ /* If the client is swapped, it's not local. Talk to the hand. */
+
+ swaps(&stuff->length, n);
+ if (sizeof(*stuff) / 4 != client->req_len)
+ return BadLength;
+
+ rep.sequenceNumber = client->sequence;
+ swaps(&rep.sequenceNumber, n);
+ rep.length = 0;
+ rep.driverNameLength = 0;
+ rep.busIdLength = 0;
+ rep.sareaHandle = 0;
+
+ return client->noClientException;
+}
+
+static int
+SProcDRI2Dispatch (ClientPtr client)
+{
+ REQUEST(xReq);
+
+ /*
+ * Only local clients are allowed DRI access, but remote clients
+ * still need these requests to find out cleanly.
+ */
+ switch (stuff->data)
+ {
+ case X_DRI2QueryVersion:
+ return ProcDRI2QueryVersion(client);
+ case X_DRI2Connect:
+ return SProcDRI2Connect(client);
+ default:
+ return BadRequest;
+ }
+}
+
+static void
+DRI2ResetProc (ExtensionEntry *extEntry)
+{
+}
+
+static int DRI2DrawableGone(pointer p, XID id)
+{
+ DrawablePtr pDrawable = p;
+
+ DRI2DestroyDrawable(pDrawable);
+
+ return Success;
+}
+
+static void
+DRI2ExtensionInit(void)
+{
+ dri2Extension = AddExtension(DRI2_NAME,
+ DRI2NumberEvents,
+ DRI2NumberErrors,
+ ProcDRI2Dispatch,
+ SProcDRI2Dispatch,
+ DRI2ResetProc,
+ StandardMinorOpcode);
+
+ dri2DrawableRes = CreateNewResourceType(DRI2DrawableGone);
+}
+
+extern Bool noDRI2Extension;
+
+_X_HIDDEN ExtensionModule dri2ExtensionModule = {
+ DRI2ExtensionInit,
+ DRI2_NAME,
+ &noDRI2Extension,
+ NULL,
+ NULL
+};